Bash:在文件名中用空格扩展大括号和 globs?

标签 bash filenames glob

我有一些文件看起来像:

/path/with spaces/{a,b,c}/*.gz

并且我需要所有匹配 a,b,c 目录子集下的 glob 的文件最终作为单个命令的参数:

mycmd '/path/with spaces/a/1.gz' '/path/with spaces/a/2.gz' '/path/with spaces/c/3.gz' ...

我关心的目录作为命令行参数出现,我将它们放在一个数组中:

dirs=( "$@" )

我想做这样的事情:

IFS=,
mycmd "/path/with spaces/{${dirs[*]}}/"*.gz

但这不起作用,因为 bash 在变量之前展开大括号。我尝试过使用 echols 甚至 eval (*shudder*) 的技巧,但很难让它们在文件名中使用空格。 find 似乎没有太大帮助,因为它不做大括号。我可以为数组中的每个目录获取一个单独的 glob:

dirs=( "${dirs[@]/#//path/with spaces/}" )
dirs=( "${dirs[@]/%//*.gz}" )

然后 bash 在扩展时引用通配符。

那么:是否有一种优雅的方式让所有文件都匹配可变大括号和 glob 模式,正确处理空格,或者我是否卡在循环中?如果这有所不同,我正在使用 Bash 3。

最佳答案

要在带空格的路径上执行大括号扩展和通配,您可以引用路径中包含空格的部分,例如

mycmd '/path/with spaces/'{a,b,c}/*.gz

使用变量值列表进行大括号扩展有点棘手,因为大括号扩展是在任何其他扩展之前完成的。除了使用可怕的 eval,我看不出有什么办法。

eval mycmd "'/path/with spaces/'{a,b,c}/*.gz"

附言然而,在这种情况下,我个人会选择循环来构建参数列表,而不是上面显示的方法。虽然更冗长,但对于外行来说,循环将更容易阅读,并且将避免使用 eval 的需要(尤其是当扩展候选者来自用户输入时!)。


概念验证:

使用虚拟命令 (x.sh) 打印出参数的数量并打印出每个参数:

[me@home]$ shopt -s nullglob  # handle case where globbing returns no match

[me@home]$ ./x.sh 'path with space'/{a,b}/*.txt
Number of arguments = 3
- path with space/a/1.txt
- path with space/b/2.txt
- path with space/b/3.txt

[me@home]:~/temp$ dirs="a,b"
[me@home]k:~/temp$ eval ./x.sh "'path with space'/{$dirs}/*.txt"
Number of arguments = 3
- path with space/a/1.txt
- path with space/b/2.txt
- path with space/b/3.txt

关于Bash:在文件名中用空格扩展大括号和 globs?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14381711/

相关文章:

python - 将多个 ip 地址的列表解析为单个变量

php - CakePHP。应用程序/控制台/蛋糕 : Permission denied for root user

python - 如何使用python将多个文件从子目录传输到单个路径文件夹?

python - 使用 glob 参数递归匹配文件名

Python文件重命名语法错误

linux - 如何使用不同的变量循环 shell 脚本,用变量存储脚本的全部内容,然后运行另一个函数

php - 如何在仅打印出有错误的文件时递归地检查所有文件?

c - 验证文件系统上的用户输入

bash - 根据文件名的第一部分将文件移动到目录?

C++ 代码文件扩展名? .cc 和 .cpp 有什么区别