使用`seq`的Bash通配符模式

时间:2016-02-24 03:46:18

标签: bash shell

我正在尝试以下命令:

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的用法?

2 个答案:

答案 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扩展的顺序已经修复的时候引入的。 功能