当在bash脚本中执行以下两行代码时,“ls”会抱怨文件不存在:
dirs=/content/{dev01,dev02}
ls -l $dirs
当我使用-x选项运行脚本时,它似乎是在单引号内传递变量(这会阻止通配):
+ dirs=/content/{dev01,dev01}
+ ls -l '/content/{dev01,dev01}'
ls: /content/{dev01,dev01}: No such file or directory
如果我从交互式shell(无引号)执行“ls”命令,它将返回两个目录。
我一直在阅读Bash参考手册(第3.2版)并且看不到任何原因导致文件名通配不发生(我没有将-f传递给shell),或者我可以设置的任何内容确保发生全球化。
答案 0 :(得分:30)
我认为这是扩展的顺序:
扩展的顺序是:
brace expansion
,代字号扩展,参数,variable
和算术扩展和 命令替换(在一个完成 从左到右的时尚),字 分裂,pathname expansion
。
因此,如果您的变量被替换,则不再进行大括号扩展。这对我有用:
eval ls $dirs
对eval要非常小心。它将逐字执行这些东西。因此,如果dirs包含f{m,k}t*; some_command
,则在ls完成后将执行some_command。它将执行您在当前shell中为eval
提供的字符串。它会将/content/dev01 /content/dev02
传递给ls,无论它们是否存在。将*
放在这些东西后使其成为路径名扩展,它将省略不存在的路径:
dirs=/content/{dev01,dev02}*
我对此并不是百分之百确定,但这对我来说很有意义。
答案 1 :(得分:22)
答案 2 :(得分:8)
这不是文件夹通配,这是大括号扩展。 区别是微妙的,但它存在 - 在文件名通配中你只会收到现有文件,而在大括号扩展中你可以生成任何类型的字符串。
http://www.gnu.org/software/bash/manual/bashref.html#Brace-Expansion
http://www.gnu.org/software/bash/manual/bashref.html#Filename-Expansion
现在,这对我有用:
#!/bin/sh
dirs=`echo ./{dev01,dev02}`
ls $dirs
答案 3 :(得分:6)
对于那些通过谷歌发现这个问题的人(像我一样),@ Pee和@ feoh的答案是"如何在bash脚本中对变量进行全局解决方案"。
list_of_results=(pattern)
会将与pattern
匹配的现有文件名保存到数组list_of_results
中。 list_of_results
的每个元素都将包含一个文件名,空格和全部。
您可以从{0}开始以"${list_of_results[<index>]}"
为<index>
访问每个结果。您可以将整个列表正确引用为"${list_of_results[@]}"
。
答案 4 :(得分:2)
我怀疑你需要的是一个数组,但这会限制你进入更新的阶段。它比使用eval更安全。
dirs=( /"content with spaces"/{dev01,dev02} )
dirs=( /content/{dev01,dev02} )
ls -l "${dirs[@]}"
/content/{dev01,dev02}
将扩展为:
"/content/dev01" "/content/dev02"
这些目录的存在与扩展无关。
将变量分配给大括号扩展时,它变得不可预测。
dirs=/content/{dev01,dev02}
可能变成
"/content/dev01"
或
"/content/dev01 /content/dev02"
或
"/content/dev01" "/content/dev02"
或
"/content/{dev01,dev02}"
如果您以任何方式引用括号,它们将不会展开,因此结果将包含大括号并且几乎毫无意义。
答案 5 :(得分:1)
由于你想要glob 文件,你不应该使用大括号扩展。在这种情况下使用大括号扩展是一个反模式,绝对是错误的工具。
你想要的是extended globbing:
shopt -s extglob # likely already set in interactive shells
dirs=/content/@(dev01|dev02)
ls $dirs
答案 6 :(得分:0)
ls `echo $dirs`
在cygwin下工作。
答案 7 :(得分:0)
没有人解决的问题是变量赋值会有所不同。
dirs=/content/{dev01,dev02}
展开方式与
不同echo /content/{dev01,dev02}
问题是如何将扩展结果分配给dirs