我很好奇为什么命令:
for f in `/bin/ls /mydir | sort | tail -n 10`; do echo $f; done;
输出/ dir中的最后十个文件,但
/bin/bash -c "for f in `/bin/ls /mydir | sort | tail -n 10`; do echo $f; done;"
在意外令牌附近输出"语法错误' [/ mydir中的文件]'"
答案 0 :(得分:5)
您正在使用双引号,因此父shell在将参数传递给/bin/bash
之前插入反引号和变量。
因此,您的/bin/bash
收到以下参数:
-c "for f in x
y
z
...
; do echo ; done;"
这是语法错误。
要避免这种情况,请使用单引号传递您的参数:
/bin/bash -c 'for f in `/bin/ls /mydir | sort | tail -n 10`; do echo $f; done;'
答案 1 :(得分:2)
子命令输出中的不同换行处理。例如,在我的机器上,使用/bin
我得到了第一个例子的输出:
rmdir
sh
sleep
stty
sync
tcsh
test
unlink
wait4path
zsh
但后者:
/bin/bash: -c: line 1: syntax error near unexpected token `sh'
/bin/bash: -c: line 1: `sh'
因为在两种情况下命令替换都发生在你的第一个 shell中,你的第一个命令就会起作用(在创建命令行时会删除换行符),但在第二种情况下它并没有&#39 ; t - 由于你的""
,它们仍保留在字符串中。使用echo
而不是bash -c
可以展示这一点:
$ echo "for f in `/bin/ls /bin | sort | tail -n 10`; do echo \$f; done"
for f in rmdir
sh
sleep
stty
sync
tcsh
test
unlink
wait4path
zsh; do echo $f; done
您可以从中看到bash -c
看到的内容及其无效的原因 - sh
位于do
之前!
您可以使用单引号,但这会导致子命令在新的子shell中运行:
$ /bin/bash -c 'for f in `/bin/ls /bin | sort | tail -n 10`; do echo $f; done'
rmdir
sh
sleep
stty
sync
tcsh
test
unlink
wait4path
zsh
如果不行,你需要摆脱这些换行符:
$ /bin/bash -c "for f in `/bin/ls /bin | sort | tail -n 10 | tr '\n' ' '`; do echo \$f; done"
rmdir
sh
sleep
stty
sync
tcsh
test
unlink
wait4path
zsh