这是非常微不足道的,我确实找到了很多答案,但仍然无法解决。我制作了一个带有参数的脚本,基本上是这样的:
var1=$1
echo "outside the pipe, my variable is set: $var1"
ls *.* | xargs sh -c 'echo "$0" "$@"; echo "inside the pipe, my variable is empty: $var1"'
我的问题是,我需要通过管道传输文件名列表以及我的一个变量。我该怎么做?我试图将我的文件列表写入一个数组,然后附加/前置我的参数并将其传递到管道中,但这确实会在以后产生问题,因为我以块的形式处理它,我的原始脚本类似于(imagemagick):
ls *.png | xargs -n 100 sh -c 'convert "$0" "$@" -evaluate-sequence $var1 ../out2/"$0"'
非常感谢任何帮助!
不,您不必通过管道传输文件名列表。
也就是说,将内部子 shell
$var1
作为第一个参数(第零个参数应该是 shell 的名称)。内部外壳
$var1
从参数列表中取出,并且对找到的第一个路径名也做同样的find
事情(我不知道为什么,但这至少使它等同于我相信你的代码所做的),然后关闭这些从$@
使用shift 2
.如果您需要以恰好 100 个为单位执行此操作:
这比管道输出更安全的原因
ls
是因为路径名是作为以 nul 结尾的列表而不是以换行符结尾的列表传递的。该sh
脚本在两种变体中都是相同的,并$var1
作为命令行参数。您的代码不起作用的原因是
sh -c
外壳不知道$var1
其父外壳。有关的:
The
sh -c
是一个新的 shell,所以你需要做一个export
of$var1
以便子进程拥有它或将它sh -c
作为参数传递给它。您的示例的另一个问题是您在单个刻度内有变量。
您实际上不必运行另一个 shell 来执行此操作。要处理与 glob 表达式匹配的所有文件,只需在最后要运行的程序的命令行上使用 glob:
如果您只需要访问部分文件,请将它们存储在数组中并对其进行切片或索引:
(
"${files[0]}"
是第一个文件名,"${files[@]:1}"
扩展到所有其他文件名)从那里,我们可以一次处理一百个文件:
也就是说,如果我
xargs
正确解释了您的命令。它似乎将第一个文件名作为第零个参数传递给sh -c
(通常作为外壳的名称)。但是要回答您提出的问题,您可以
export
使用变量使其对内壳可见,或者将其放在双引号中以使其被外壳扩展。例如或者
两者都输出
foo bar
。传递环境更好,因为语法更清晰(注意在后者周围$var
和$1
中的不同类型的引号),并且变量值中的任何引号都不会引起问题,就像在第二种情况下一样。