在 bash 或 zsh 中循环遍历一个文件扩展名或另一个文件扩展名

ale*_*lex 2 bash zsh for

这在语法上是正确的:

for f in *bw;do echo $f;done
Run Code Online (Sandbox Code Playgroud)

但是我如何添加一个扩展来循环其中一个?

cas*_*cas 8

你不知道。您迭代两个“扩展”并(如果需要)检查其中一个或两个是否存在。例如,如果您只想打印一个或另一个(看到的第一个),请保留每个文件的基本名称(不带扩展名)的列表 - 关联数组对此很有用,因为它很容易查找。例如在 bash 中:

declare -A files

for f in *.bw *.txt; do
  bn=${f%.*}
  if [ -z "${files[$bn]}" ] ; then
    echo "$f"
    files["$bn"]=1
  fi
done
Run Code Online (Sandbox Code Playgroud)


Mic*_*mer 6

在 Bash 中shopt -s extglob以及 zshKSH_GLOB启用:

\n
for f in *.@(bw|txt)\n
Run Code Online (Sandbox Code Playgroud)\n

请注意,在 bash 中,如果没有匹配项,则循环将运行并$f设置为文字字符串*.@(bw|txt)。为了避免这种情况,在 bash 中:

\n
shopt -s nullglob\nfor f in *.@(bw|txt)\n
Run Code Online (Sandbox Code Playgroud)\n

在 zsh 中,默认情况下,如果没有匹配项,您将收到错误消息。为了避免这种情况,请添加N glob 限定符

\n
for f in *.@(bw|txt)(N)\n
Run Code Online (Sandbox Code Playgroud)\n

在 zsh 中,有一个更简单的解决方案,可以使用默认选项,再次使用(N)如果没有匹配项,则不执行任何操作:

\n
for f in *.(bw|txt)(N)\n
Run Code Online (Sandbox Code Playgroud)\n

所有这些都将按字母顺序对所有条目进行排序,两个扩展名混合的文件(即,仅扩展名不同的重复名称将(可能\xc2\xb9)是连续的)。您可以根据需要在括号内列出尽可能多的以竖线分隔的模式条目,并且它们可以包含更多的通配符(例如(zip|tar.?z))。

\n
\n

然而, \xc2\xb9foo.bw foot.bw foot.txt foo.txt会按语言环境中的顺序进行排序,在.排序规则算法中首先会忽略该顺序,这在当今很常见(如footborfoott在之前footx和之后foobw)。

\n

  • 在 Bash 上,可能是 `shopt -s nullglob`,因此如果不存在匹配文件,它不会运行将 `f` 设置为字面值 `*.@(bw|txt)` 的循环。 (2认同)