观察:
mark@L-R910LPKW:~$ echo a b | xargs -d' ' -I{} bash -c 'echo {} 1'
a 1
b
bash: line 2: 1: command not found
mark@L-R910LPKW:~$
到底是怎么回事?
观察:
mark@L-R910LPKW:~$ echo a b | xargs -d' ' -I{} bash -c 'echo {} 1'
a 1
b
bash: line 2: 1: command not found
mark@L-R910LPKW:~$
到底是怎么回事?
什么地方出了错
b
出现在输出中,所以它被处理了,只是不是你期望的方式。作为第一步,让 bash 告诉您它看到了什么:传递选项
-x
以启用其跟踪。echo a 1
所以 bash 是按预期首先调用的代码行。但下一行echo b
并不echo b 1
像您预期的那样。还有一条额外的线与1
. 为什么?好吧,您告诉 xargs 在空格处拆分。您将输入传递给
a b
换行符
。所以 xargs 看到输入包含两个片段:a
和b
。按照指示,xargs 为每个片段调用 bash:首先执行echo a 1
,然后执行echo b1
。如何做对
某些版本的
find
orxargs
让您嵌入{}
shell 片段中。这几乎总是一个坏主意,它会破坏一些文件名或其他数据,并且通常是一个安全漏洞。将数据作为单独的参数传递。是否可以安全地使用 `find -exec sh -c`?
正如Gilles 在他们的回答中提到的那样,
-d ' '
GNU xargs 的选项让它考虑空格,并且只考虑空格作为分隔符,将换行符作为数据的一部分,在这里像字母本身一样嵌入到您的 shell 代码中。那可能不是你想要的。(可能最常见的用途-d
是-d '\n'
告诉它按原样使用行,而不像 eg 那样进行任何进一步处理-L
。)相反,如果您想将每个以空格分隔的单词作为一个单独的项目,一种选择是利用默认行为,它在空格上拆分项目,因此可以直接使用:
请注意,它还处理引号和反斜杠(与 shell 略有不同),因此这与仅使用空格作为分隔符不同。输入
a "b c"
将产生项目a
和b c
。或者,您可以使用
-d
withtr
对输入进行预处理,并将要用作分隔符的所有字符折叠为一个字符:但是,
-d
这不是标准的,我认为只在 GNU xargs 中实现,所以你可能想改用-0
它有更广泛的支持:在任何情况下,都应避免将值直接嵌入到 shell 代码段中,因为这样做是不安全的,并且不可能正确处理任意值。