在 bash 脚本中将通配符替换为文件路径作为参数后如何扩展通配符?

How to expand wildcards after substituting them into a filepath as arguments, in bash script?

我目前正在尝试将参数替换为文件路径

FILES=(~/some/file/path/${1:-*}*/${2:-*}*/*)

我正在尝试有选择地替换变量,这样如果没有参数,路径看起来像 ~/some/file/path/**/**/*,如果只有一个,它看起来像 ~/some/file/path/arg1*/**/*,等等。但是,我需要在构建文件路径后进行通配符扩展。目前似乎正在发生的事情是文件路径作为带有星号的单个文件路径进入 FILES。

更广泛的目标是将当前目录下两级的所有子目录传递到 FILES 变量中,除非给出参数,在这种情况下,第一个参数用于选择特定目录第一层,第二个参数为第二层。

编辑:

此脚本生成目录,然后从中抓取随机文件,之前使用 ** 而不是 *,但它仍然有效,并且在给定参数时正确地限制要从中提取的文件。问题已解决。

#!/bin/bash

mkdir dir1 dir1/a
touch dir1/a/foo.txt dir1/a/bar.txt
cp -r dir1/a dir1/b
cp -r dir1 dir2

files=(./*${1:-}/*/*)

for i in {1..10}
do
    # Get random file
    nextfile=${files[$RANDOM % ${#files[@]} ]}

    # Use file
    echo "$nextfile" || break

    sleep 0.5
done

rm -r dir1 dir2

我无法重现此行为。

$ files=( ~/tmp/foo/${1:-*}*/${2:-*}*/* )
$ declare -p files
declare -a files='([0]="/Users/chaduffy/tmp/foo/bar/baz/qux")'

解释为什么这应该有效:参数扩展发生在 glob 扩展之前,因此在 glob 扩展发生时,内容已经扩展。有关详细信息,请参阅 lhunath's simplified diagram of the bash parse/expansion process

可能的解释很简单,您的 glob 没有匹配项,因此正在对自身求值。可以使用 nullglob 开关禁用此行为,这将为您提供一个空数组:

shopt -s nullglob
files=(~/some/file/path/${1:-*}*/${2:-*}*/*)
declare -p files

另一个注意事项:** 仅在 shopt -s globstar 已成为 运行 且此功能(在 4.0 中添加)可用的 shell 中具有特殊含义。在 Mac OS X 上(没有通过 MacPorts 或类似的方式安装更新版本的 bash),它不存在;您需要使用 find 进行递归操作。如果您的 glob 仅在 ** 触发递归时才匹配,这将解释所讨论的行为。