扩展全局模式的最佳方法?

Rog*_*ach 42 bash wildcards

我需要以编程方式将 glob 模式(如../smth*/*, 或/etc/cron*/)扩展到文件列表中。最好的方法是什么?

man*_*ork 55

让它在数组声明的右侧展开:

list=(../smth*/)          # grab the list
echo "${#list[@]}"        # print array length
echo "${list[@]}"         # print array elements
for file in "${list[@]}"; do echo "$file"; done  # loop over the array
Run Code Online (Sandbox Code Playgroud)


注意nullglob需要设置shell选项。
默认情况下未设置。
它可以防止在 glob(或多个 glob 之一)与任何名称不匹配的情况下出错。

将其设置bash

shopt -s nullglob
Run Code Online (Sandbox Code Playgroud)

zsh

setopt nullglob
Run Code Online (Sandbox Code Playgroud)

  • 啊, shopt -s nullglob 解决了它。 (5认同)
  • 有一个问题。如果模式没有匹配任何文件,它会自行打印 - 这不是很好。 (2认同)

Wal*_*alf 8

compgen是一个 Bash 内置程序,您可以将转义(!)模式传递给它,它会输出匹配项,根据是否存在返回 true 或 false。如果您需要从变量/脚本参数传递全局模式,这尤其有用。

glob_pattern='../smth*/*'
while read -r file; do
    # your thing
    echo "read $file"
done < <(compgen -G "$glob_pattern" || true)
Run Code Online (Sandbox Code Playgroud)

添加 || true可防止错误返回compgen导致任何问题。此方法避免了没有匹配的问题,并且不需要更改 nullglob 选项。

如果您需要数组中的项目,只需files=()在循环之前和files+=("$file")循环内部初始化一项即可。然后,您可以通过简单地使用 来检查数组的长度来查看是否有任何匹配项if [[ ${#files[@]} -gt 0 ]]; then

  • @resolritter 我刚刚运行了 `compgen -G '/**/*.gz'` (在 bash v4.2.46 上),它发现了几个具有组合扩展名的文件。我还有 shell 选项 `globstar` `off`。您是说“compgen -G '**/*.bin'”不会产生“echo **/*.bin”产生的输出吗? (2认同)