bash 迭代文件列表,除非为空

sym*_*ean 54 bash parameter

我认为这很简单 - 但事实证明它比我预期的要复杂。

我想遍历目录中特定类型的所有文件,所以我这样写:

#!/bin/bash

for fname in *.zip ; do
   echo current file is ${fname}
done
Run Code Online (Sandbox Code Playgroud)

只要目录中至少有一个匹配的文件,这就会起作用。但是,如果没有匹配的文件,我会得到:

current file is *.zip
Run Code Online (Sandbox Code Playgroud)

然后我尝试:

#!/bin/bash

FILES=`ls *.zip`
for fname in "${FILES}" ; do
    echo current file is ${fname}
done
Run Code Online (Sandbox Code Playgroud)

当没有文件时循环体不执行,我从 ls 收到错误:

ls: *.zip: No such file or directory
Run Code Online (Sandbox Code Playgroud)

如何编写一个干净地处理没有匹配文件的循环?

che*_*ner 64

在 中bash,您可以设置该nullglob选项,以便不匹配任何内容的模式“消失”,而不是将其视为文字字符串:

shopt -s nullglob
for fname in *.zip ; do
   echo "current file is ${fname}"
done
Run Code Online (Sandbox Code Playgroud)

在 POSIX shell 脚本中,您只需验证它是否fname存在(同时使用[ -f ],检查它是常规文件(或常规文件的符号链接)而不是其他类型,如目录/fifo/device...):

for fname in *.zip; do
    [ -f "$fname" ] || continue
    printf '%s\n' "current file is $fname"
done
Run Code Online (Sandbox Code Playgroud)

如果要遍历名称以任何类型结尾的所有(非隐藏)文件,请替换[ -f "$fname" ]为。[ -e "$fname" ] || [ -L "$fname ].zip

更换*.zip.*.zip .zip *.zip,如果你还需要考虑隐藏文件的名义结束.zip

  • `shopt -s nullglob` 在 Ubuntu 17.04 上对我不起作用,但是 `[ -f "$fname" ] || 继续`运作良好。 (2认同)
  • @koppor 听起来您实际上并没有使用`bash`。 (2认同)