将从 xargs 传递给 bash 的参数保存为用于处理的变量
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/36186394/
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
Saving arguments passed from xargs to bash as a variable for processing
提问by Ian Fiddes
I am trying to run many commands in parallel, and need to do some string manipulation on the input first. How can I make the below example work?
我正在尝试并行运行许多命令,并且需要先对输入进行一些字符串操作。我怎样才能让下面的例子工作?
find . -mindepth 1 -type d | xargs -n 1 -P 20 -i sh -c "v={}; echo $v"
When I use this, $v
is null. Why is it not being saved as the value of {}
?
当我使用它时,$v
为空。为什么它没有被保存为的值{}
?
采纳答案by Mike Holt
The parent shell is expanding $v
beforethe string gets passed to xargs
.
父外壳扩展$v
之前的字符串被传递给xargs
。
Suppose your find
command finds a subdirectory named ./stuff
.
假设您的find
命令找到一个名为./stuff
.
First, the parent bash
shell (the one you typed the find
command into) will expand $v
, because the string is in double quotes. You currently have no value set for variable v
, so it expands to an empty string.
首先,父bash
shell(你输入find
命令的那个)将 expand $v
,因为字符串是双引号。您当前没有为 variable 设置值v
,因此它扩展为空字符串。
Next, the arguments get passed to xargs
, which will see this: v={}; echo
接下来,参数被传递给xargs
,它将看到:v={}; echo
Then, xargs
will read ./stuff
from the pipe, and replace {}
with ./stuff
然后,xargs
将从./stuff
管道中读取,并替换{}
为./stuff
Finally, the sh
command is executed by xargs
, and sh
will see this: v=./stuff; echo
最后,sh
命令由xargs
,执行,sh
将看到:v=./stuff; echo
To fix this, you need to either escape the $
so that the parent shell doesn't expand it, or use single quotes to avoid variable expansion. You should also probably quote the strings so that any directory names with spaces in them don't cause problems with the final sh
command:
要解决此问题,您需要转义$
以便父 shell 不会扩展它,或者使用单引号来避免变量扩展。您可能还应该引用字符串,以便任何包含空格的目录名称都不会导致最终sh
命令出现问题:
find . -mindepth 1 -type d | xargs -n 1 -P 20 -i sh -c "v=\"{}\"; echo \"$v\""
OR
或者
find . -mindepth 1 -type d | xargs -n 1 -P 20 -i sh -c 'v="{}"; echo "$v"'
With either command, the final sh
process will see: v="./stuff"; echo "$v"
使用任一命令,最终sh
过程将看到:v="./stuff"; echo "$v"
By the way, one way to see for yourself that this is indeed what is happening would be to set a value for v
in the parent shell, then run your original command. The shell will expand $v
to whatever value you set, and you will see that value repeated for every directory found by find
.
顺便说一句,亲眼看到这确实发生了什么的一种方法是v
在父 shell 中设置一个值,然后运行您的原始命令。shell 将扩展$v
为您设置的任何值,并且您将看到该值对find
.
$ v=foobar
$ find . -mindepth 1 -type d | xargs -n 1 -P 20 -i sh -c "v={}; echo $v"
foobar
foobar
foobar
foobar
foobar
foobar
foobar
foobar
foobar
foobar
foobar
...
回答by Ole Tange
With GNU Parallel you would do:
使用 GNU Parallel,您可以:
find . -mindepth 1 -type d | parallel -P 20 'v={}; echo "$v"'