bash 参数列表太长时如何正确使用“xargs”

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/683776/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-17 20:46:55  来源:igfitidea点击:

How to use "xargs" properly when argument list is too long

linuxbashunix

提问by jparanich

Can someone please give me an example of using xargs on the below operation?

有人可以给我一个在下面的操作中使用 xargs 的例子吗?

tar c $dir/temp/*.parse\
    | lzma -9 > $dir/backup/$(date '+%Y-%m-%d')-archive.tar.lzma

I get the error from bash "/bin/tar: Argument list too long"

我从 bash 收到错误“ /bin/tar:参数列表太长

Particularily I am trying to do LZMA compression on about 4,500 files; so this isn't surprising. I just don't know how to modify the above to use xargs and get rid of the error! Thanks.

特别是我正在尝试对大约 4,500 个文件进行 LZMA 压缩;所以这并不奇怪。我只是不知道如何修改上面的使用 xargs 并摆脱错误!谢谢。

回答by Joachim Sauer

Expanding on CristopheDs answer and assuming you're using bash:

扩展 CristopheDs 答案并假设您正在使用 bash:

tar c --files-from <(find $dir/temp -maxdepth 1 -name "*.parse") | lzma -9 > $dir/backup/$(date '+%Y-%m-%d')-archive.tar.lzma

The reason xargsdoesn't help you here is that it will do multiple invocations until all arguments have been used. This won't help you here since that will create severaltar archives, which you don't want.

xargs这里对您没有帮助的原因是它会执行多次调用,直到使用完所有参数。这在这里对您没有帮助,因为这会创建几个您不想要的 tar 档案。

回答by lhunath

As a side note:

作为旁注:

Always, always avoid xargs(1). It's a broken tool and is only remotely useful if you use it with the -0 option. Even then, it's almost always better to use find(1)'s -exec option, or a simple for or while loop.

总是,总是避免 xargs(1)。这是一个损坏的工具,只有在您将它与 -0 选项一起使用时才有用。即便如此,使用 find(1) 的 -exec 选项或简单的 for 或 while 循环几乎总是更好。

Why is xargs so bad? Firstly, it splits input on whitespace, meaning all your filenames that containwhitespace will cause havoc. Secondly, it triesto be a smartass, and parse quotesfor you. Which only leads to more headaches as you use it on filenames that containquotes as part of the filename, such as songs: "I don't wanna miss a thing.mp3". This will just make xargs puke and curse at you that you quoted its input badly. No, you didn't: it should just learn that quotes do not belong in input data, they belong in shell scripts, and xargs has no business trying to parse them.

为什么 xargs 如此糟糕?首先,它将输入拆分为空格,这意味着所有包含空格的文件名都会造成严重破坏。其次,它试图成为一个聪明人,并为你解析引号。当您将它用于包含引号作为文件名一部分的文件名时,这只会导致更多的麻烦,例如歌曲:“我不想错过 thing.mp3”。这只会让 xargs 呕吐并诅咒你,你引用了它的输入。不,你没有:它应该知道引号不属于输入数据,它们属于 shell 脚本,并且 xargs 没有尝试解析它们的业务。

Mind you, xargs(1) doesn't do the whitespace splitting or the quote parsing when you pass -0 to it. It does the right thing, which is use NULL bytes to delimit filenames. But that means you need to give it input that uses NULL byte-delimited filenames (such as "find -foo -print0"). Which brings us back to: it's better to just use find's -exec: "find -foo -exec bar {} +".

请注意,当您将 -0 传递给 xargs(1) 时,它不会进行空格拆分或引号解析。它做正确的事情,即使用 NULL 字节来分隔文件名。但这意味着您需要为其输入使用 NULL 字节分隔的文件名(例如“ find -foo -print0”)。这让我们回到:最好只使用 find 的 -exec:“ find -foo -exec bar {} +”。

回答by ChristopheD

Use find to pipe the 'wanted' filenames to a temporary file, and then use tar with the '-–files-from' command line option.

使用 find 将“想要的”文件名通过管道传输到临时文件,然后将 tar 与“-–files-from”命令行选项一起使用。

Edit:

编辑:

or pipe them directly into each other to avoid the temporary file.

或通过管道将它们直接相互连接以避免临时文件。

So: use find to list the wanted filenames | tar ... --files-from

所以:使用 find 列出想要的文件名 | tar ... --files-from

回答by Zoredache

Perhaps you want something like this?

也许你想要这样的东西?

find $dir/temp/ -name '*.parse' -print0 | tar --null -T - -c | lzma -9 > $dir/backup/$(date '+%Y-%m-%d')-archive.tar.lzma

回答by Jonathan Leffler

Since you're on Linux, you have GNU tar, and you can use the '-F -' or '--files-from' option to read the file names.

由于您使用的是 Linux,因此您拥有 GNU tar,并且可以使用“ -F -”或“ --files-from”选项来读取文件名。

However, you can also use:

但是,您也可以使用:

--use-compress-program="lzma -9"

--use-compress-program="lzma -9"

to specify the compression program to use, and simply give the compresses file name as the target file for the 'tar' command.

指定要使用的压缩程序,只需将压缩文件名作为“tar”命令的目标文件即可。

This was necessary for 'bzip2' compression before the '-j' option was added.

-j在添加' ' 选项之前,这对于 'bzip2' 压缩是必需的。