我可以eval
在下面的示例中避免还是没有其他方法?变量上的文件列表是动态的,我想对所有文件进行 cksum 。该目录中还有许多其他文件,但应该忽略它们。
$ Z="file1 file4"
$ echo ${Z//\ /,}
file1,file4
$ echo {${Z//\ /,}}
{file1,file4}
$ cksum {file1,file4}
927007485 136284 file1
2748059092 136286 file4
$ cksum {${Z//\ /,}}
cksum: {file1,file4}: No such file or directory
$ eval cksum {${Z//\ /,}}
927007485 136284 file1
2748059092 136286 file4
答案1
使用数组代替字符串:
files=( file1 file2 "filename with spaces" file50 "*my* file" )
cksum "${files[@]}"
请注意,上面的每个双引号都很重要,特别是当您的文件名中包含空格或文件名通配字符时。
答案2
解释为什么cksum {${Z//\ /,}}
没有按您的预期工作:
- 根据 bash替换/扩展的顺序,发生大括号扩展前参数替换
- 然而,它被记录在案“为了避免与参数扩展发生冲突,字符串 '${' 不被视为符合大括号扩展条件。” -- 所以 bash 在这里不执行大括号扩展。
- 然后 shell 最终进行参数替换,命令扩展为
cksum {file1,file4}
- shell 不会返回并重新执行扩展列表,因此我们不会再次进行大括号扩展:我们只剩下单个单词“{file1,file4}”
- 并且没有这样的文件。
当您引入eval
混合时,您明确要求 shell 再次检查扩展列表。现在我们可以在命令上进行大括号扩展cksum {file1,file4}
,然后您可以获得这两个文件的校验和。