对几个解决方案(以及您自己的测试)的重大警告:
当你做:任何事情 | xargs 的东西
xargs 将尝试在“某物”之后放置“尽可能多的参数”,但最终您可能会多次调用“某物”。
所以你的尝试:find ... | xargs tar czvf 文件.tgz
在 xargs 每次调用“tar”时可能最终会覆盖“file.tgz”,而您最终只会得到最后一次调用! (选择的解决方案使用 GNU -T 特殊参数来避免该问题,但并非每个人都有可用的 GNU tar)
你可以这样做:
find . -type f -print0 | xargs -0 tar -rvf backup.tar
gzip backup.tar
cygwin 上的问题证明:
$ mkdir test
$ cd test
$ seq 1 10000 | sed -e "s/^/long_filename_/" | xargs touch
# create the files
$ seq 1 10000 | sed -e "s/^/long_filename_/" | xargs tar czvf archive.tgz
# will invoke tar several time as it can'f fit 10000 long filenames into 1
$ tar tzvf archive.tgz | wc -l
60
# in my own machine, I end up with only the 60 last filenames,
# as the last invocation of tar by xargs overwrote the previous one(s)
# proper way to invoke tar: with -r (which append to an existing tar file, whereas c would overwrite it)
# caveat: you can't have it compressed (you can't add to a compressed archive)
$ seq 1 10000 | sed -e "s/^/long_filename_/" | xargs tar rvf archive.tar #-r, and without z
$ gzip archive.tar
$ tar tzvf archive.tar.gz | wc -l
10000
# we have all our files, despite xargs making several invocations of the tar command
注意:xargs 的行为是众所周知的错误,这也是为什么,当有人想做的时候:
find .... | xargs grep "regex"
他们必须写出来:
find ..... | xargs grep "regex" /dev/null
这样,即使 xargs 对 grep 的最后一次调用只附加了 1 个文件名,grep 也会看到至少 2 个文件名(每次都有:/dev/null,它不会找到任何东西,并附加了 the filename(s)通过 xargs 之后),因此当某些东西匹配“正则表达式”时将始终显示文件名。否则,您最终可能会看到最后的结果显示前面没有文件名的匹配项。