反引号意思是“在反引号之间运行一个命令作为命令,然后就像我在这里输入该命令的输出一样”。正如其他人所说,单引号的意思是一个文字串。因此,在第一种情况下,会发生什么情况是这样的:
的bash运行ls -v *.mkv
为命令,其输出是这样的:
fileName1.mkv
fileName2.mkv
的bash然后替换这回反引号包围的命令在何处,即它有效地使你的for
发言到此:
for i in fileName1.mkv fileName2.mkv; do echo $i; done
有两个“令牌”:“fileName1.mkv”和“fileName2.mkv”,所以循环运行它的身体(echo $i
)两次,第一次为每个:
echo fileName1.mkv
echo fileName2.mkv
默认情况下,echo
命令将输出后,新行完呼应你告诉它呼应,所以你会得到对自己行,你所期望的输出每个文件名。
但是,如果使用单引号而不是反引号,则单引号之间的内容不会被评估;即bash并不认为它是一个命令(或者根本没有什么特别的;单引号告诉bash,“这个文本不是特别的;不要试图评估它或者对它做任何事情”)。因此,这意味着你正在运行的是这样的:
for i in 'ls -v *.mkv'; do echo $i; done
它只有一个令牌,文本字符串“LS -v * .MKV”,所以循环体只运行一次:
echo ls -v *.mkv
......但在bash运行之前echo
,它扩展了“* .mkv”。
我掩盖了这上面,但是当你这样做ls *.mkv
,它实际上不是ls
做的*.mkv
转化为所有的.mkv文件名列表;这是真的。 ls
从来没有看到*.mkv
;到ls
运行时,bash用“fileName1.mkv fileName2.mkv ...”代替它。
同样,对于echo
:运行此行之前,bash的扩展*.mkv
,那么什么是真正运行是:
echo ls -v fileName1.mkv fileName2.mkv
它输出这样的文字:
ls -v fileName1.mkv fileName2.mkv
(*脚注:还有另一件事我反省了,这就是文件名中的空格。反引号之间的ls
的输出是一个文件名列表,每行一个。问题是,bash将任何空格 - 包括空格和换行符都视为分隔符,s o如果你的文件名是:
file 1.mkv
file 2.mkv
你的循环将运行四次( “文件”, “1.mkv”, “文件”, “2.mkv”)。有人提到的其他形式的循环,for i in *.mkv; do ...
没有这个问题。为什么?因为当bash扩展“* .mkv”时,它会在幕后做一个聪明的事情,并将每个文件名作为一个单位来对待,就好像你在引号中所说的“file 1.mkv”“file 2.mkv”一样。在使用ls
的情况下,它不能这样做,因为在将扩展的文件名列表传递给ls
后,bash无法知道返回的是那些相同文件名的列表。 ls
可能是任何命令。)
不要使用'ls'。只需使用'for in in * .mkv;做回声“$我”; ' – anubhava
'表达',将输出确切的字符串。 'expression'执行表达式的内容并且echo输出它。 – Zohar81
看看这篇文章:http://askubuntu.com/a/20041/336375 – Cyrus