bash: /bin/tar: Argument list too long

Feb 14, 2007

Anyone who has worked with large numbers of files has seen the error ’Argument list too long’ returned by a command before, usually something like cp or rm. Eventually, they find xargs and all is well again; rather than globbing directly, you use find and xargs to feed the intended command:

~/tmp$ ls | wc -l
77029
~/tmp$ cp * /foo/bar/
bash: /bin/cp: Argument list too long
~/tmp$ find . -print0 | xargs -0 -I {} cp {} /foo/bar/

For those who don’t know, that final command is running find, which simply prints a list of the files in the current directory. xargs then passes a not-too-long subset of that list to cp in batches, replacing the {} with said list. The -print0 tells find to terminate each filename with a null character rather than the default newline, so that weird filenames work; the corresponding option -0 must be used with xargs so that it looks for that syntax. Now, on to the problem of the day.

I know xargs, but for the problem I had, I didn’t think it would help (more on that later). I wanted to tar up a whole bunch of files, too many for the command line to handle. The solution was simple, for tar provides an option to receive its list of files that makeup an archive from a file:

~/tmp$ find . -print > baz.lst
~/tmp$ tar -cf baz.tar --files-from baz.lst

Simple. There’s probably a way to one-line that, but simply piping the output of find to tar with --files-from - didn’t work, and I didn’t spend any more time trying to figure it out. As I said previously, I didn’t think xargs would help, but I pulled up the tar manpage and, using the -r option, you can append to an existing archive, which could work in conjunction with xargs just fine.