我正在尝试以下命令:
ls myfile.h1.{`seq -s ',' 3501 3511`}*
但是ls
引发了错误:
ls: cannot access myfile.h1.{3501,3502,3503,3504,3505,3506,3507,3508,3509,3510,3511}*: No such file or directory
似乎ls
认为整行是文件名而不是通配符模式。但是,如果我只是在终端中复制该命令ls myfile.h1.{3501,3502,3503,3504,3505,3506,3507,3508,3509,3510,3511}*
,我会按预期获得列表。
为什么要在完整的工作中输入命令,而不是seq
的用法?
答案 0 :(得分:5)
seq
,请尝试
$ ls myfile.h1.{3500..3511}
如果您想使用seq
我建议使用格式选项
$ ls $(seq -f 'myfile.h1.%g' 3501 3511)
但我认为没有任何理由这样做。
<强>更新强> 请注意,我没有注意到原帖中的globbing。有了这个,支撑延伸仍然是首选方式
$ ls myfile.h1.{3500..3511}*
如果你的bash支持零填充,或许甚至可以将公共数字排除在外
$ ls myfile.h1.35{00..11}*
如果没有,你可以提取至少3个
$ ls myfile.h1.3{500..511}*
请注意,seq
替代方法不适用于globbing。
其他答案有更多细节......
答案 1 :(得分:4)
karakfa's answer是正确的解决方案。
至于为什么你的方法不起作用:
Bash的brace expansion {...}
仅适用于文字表达式 - 既不是变量引用,也不像命名替换那样({{1} },或者,最好是`...`
)工作 [1] - 有关简明的概述,请参阅我的this answer。
但是,小心使用$(...)
,可以解决此限制;说:
eval
@ghoti建议在评论中进行以下改进,以便在此处使用from=3501 to=3511
# CAVEAT: Only do this if you TRUST that $from and $to contain
# decimal numbers only.
eval ls "myfile.h1.{$from..$to}*"
安全:
eval
至于如何实际评估您的命令:
注意:Bash适用7-8 kinds of expansions to a command line;下面仅讨论实际发挥作用的那些。
首先,命令replace # Use parameter expansion to remove all non-digit characters from the values
# of $from and $to, thus ensuring that they either contain only a decimal
# number or the empty string; this expansion happens *before* eval is invoked.
eval ls "myfile.h1.{${from//[^0-9]/}..${to//[^0-9]/}}*"
中的命令被执行,并被其输出替换(也记下尾随`seq -s ',' 3501 3511`
):
,
然后,结果形成一个单词,其前缀为3501,3502,3503,3504,3505,3506,3507,3508,3509,3510,3511,
及其后缀myfile.h1.{
,产生:
}*
然后将路径名扩展(globbing)应用于结果 - 在您的情况下,因为没有文件匹配,所以它保留为 as-is (默认情况下; shell选项{{1} }或myfile.h1.{3501,3502,3503,3504,3505,3506,3507,3508,3509,3510,3511,}*
可能会改变这种情况。
最后, literal shopt -s nullglob
被传递给shopt -s failglob
,因为它没有引用现有的文件系统项 - 导致错误你看到的消息。
[1]注意,该限制仅适用于序列大括号扩展(例如myfile.h1.{3501,3502,3503,3504,3505,3506,3507,3508,3509,3510,3511,}*
); list 大括号扩展(例如,ls
)不受影响,因为不需要预先解释(插值);例如{1..3}
有效,因为大括号展开会将列表展开为单独的单词{1,2,3}
和{$HOME,$USER}
,这些单词仅在以后展开。
从历史上看,序列大括号扩展是在shell扩展的顺序已经修复的时候引入的。
功能