如何将一个globexpression式分配给一个Bash脚本中的variables?
当在bash脚本中执行以下两行代码时,“ls”会抱怨文件不存在:
dirs=/content/{dev01,dev02} ls -l $dirs
当我使用-x选项运行脚本时,它似乎是在单引号内传递variables(这会阻止匹配):
+ 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),或者我可以设置的任何东西来确保globbing发生。
我认为这是扩张的顺序:
扩展的顺序是:
brace expansion
,波形扩展,参数,variable
和算术扩展和命令replace(按照从左到右的方式完成),分词和pathname expansion
。
所以如果你的variables被replace,支撑扩展不会再发生。 这适用于我:
eval ls $dirs
eval要非常小心。 它会逐字执行。 所以如果dirs包含f{m,k}t*; some_command
f{m,k}t*; some_command
,some_command将在ls完成后执行。 它会执行你在当前shell中给eval
的string。 它会将/content/dev01 /content/dev02
给ls,不pipe它们是否存在。 在东西之后放*
会使path名扩展,并且会省略不存在的path:
dirs=/content/{dev01,dev02}*
我对此并不十分确定,但对我来说是有道理的。
这里是你正在尝试做的一个很好的讨论。
简单的答案是你想要一个数组:
dirs=(/content/{dev01,dev01})
但是你对结果的处理可能会比我想象的要复杂得多。
这不是文件名拼写,这是大括号扩展。 差别是微妙的,但它存在 – 在文件名globbing你只会收到现有的文件作为结果,而在大括号扩展,你可以生成任何types的string。
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
我怀疑你需要的是一个数组,但这会限制你更新的bashes。 这比使用eval更节省。
dirs=( /"content with spaces"/{dev01,dev02} ) dirs=( /content/{dev01,dev02} ) ls -l "${dirs[@]}"
/content/{dev01,dev02}
将扩展到:
"/content/dev01" "/content/dev02"
这些目录的存在与扩展无关。
将variables分配给括号扩展时变得不可预知。
dirs=/content/{dev01,dev02}
可能会变成
"/content/dev01"
要么
"/content/dev01 /content/dev02"
要么
"/content/dev01" "/content/dev02"
要么
"/content/{dev01,dev02}"
如果你以任何方式引用大括号,它们将不会扩展,所以结果将包含大括号,并且大部分是毫无意义的。
对于像我这样的人来说,通过Googlefind这个问题,@Peter和@ feoh的答案是“如何在bash脚本中使用globvariables”的一般解决scheme。
list_of_results=(pattern)
将现有的匹配pattern
文件名保存到数组list_of_results
。 list_of_results
每个元素将保存一个文件名,空格和全部。
您可以从0开始为<index>
访问每个结果为"${list_of_results[<index>]}"
。您可以将整个列表正确引用为"${list_of_results[@]}"
。
ls `echo $dirs`
在cygwin下工作。
既然你想要glob 文件,你不应该使用大括号扩展。 在这种情况下使用括号扩展是一个反模式 ,绝对是工作的错误工具。
你想要的是扩展globbing :
shopt -s extglob # likely already set in interactive shells dirs=/content/@(dev01|dev02) ls $dirs