如何将一个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_resultslist_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