$cmd 与 eval $cmd 有何区别?为何要在cmd前使用eval?
为什么bash脚本里
$cmd和eval $cmd执行效果会不一样? 你写的这段脚本在大多数普通场景下,$cmd和eval $cmd看起来效果相同,但当传入的参数包含空格、通配符、引号这类特殊字符时,两者的差异就会显现:
1. 处理带空格的文件名
比如执行脚本时传入带空格的文件名参数:./script.sh "my document.txt"
- 直接跑
$cmd时,bash会把cmd变量里的字符串按空格拆分成ls、-rtl、my、document.txt,相当于执行ls -rtl my document.txt——这会把my和document.txt当成两个独立文件,大概率报错(除非这两个单独文件存在)。 - 用
eval $cmd时,bash会重新解析整个命令字符串,正确识别my document.txt是一个完整的文件名,相当于执行ls -rtl "my document.txt",能正常列出目标文件。
2. 处理通配符或带引号的通配符
比如传入参数"*.txt"(带引号):
- 直接
$cmd会把*.txt当成一个字面意义的文件名,如果当前目录没有叫*.txt的文件,就会报错。 eval $cmd会重新解析命令,把通配符*.txt展开成当前目录下所有的txt文件,执行ls -rtl a.txt b.txt ...,符合预期。
3. 处理带特殊字符的文件名
比如传入带单引号的文件名:./script.sh "file'name.txt"
- 直接
$cmd会把字符串拆成file、'name.txt,执行时shell会把单引号当成语法符号,导致命令解析错误。 eval $cmd会正确解析整个文件名,把file'name.txt当成一个整体处理,正常执行。
核心区别
直接展开$cmd只是做简单的空格分割,不会重新识别shell的元字符(比如引号、通配符);而eval会让shell重新完整解析一遍命令字符串,还原你原本想要的命令执行逻辑,尤其是当参数里包含特殊字符时,eval才能保证命令被正确解读。
内容的提问来源于stack exchange,提问作者steffen
相关产品推荐
相关产品推荐

