我很好奇为什么命令:
for f in `/bin/ls /mydir | sort | tail -n 10`; do echo $f; done;
输出/mydir中的最后十个文件,但
/bin/bash -c "for f in `/bin/ls /mydir | sort | tail -n 10`; do echo $f; done;"
输出"意外标记'[mydir]'附近的语法错误"
您使用的是双引号,因此父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;'
子命令输出中的不同换行处理。例如,在我的机器上,使用/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中,所以第一个命令行有效(在生成命令行时会去掉换行符),但在第二种情况下则不然——由于""
,换行符仍保留在字符串中。使用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