我的情况是我有一个名为'file.txt'的文件,它是一堆文件的列表,如下所示:
/path/{a,b,c}/file.d
/path/file.e
/path/file.f
然后我写了一个包含从这个文件中读取循环的bash文件:
#!/bin/bash
while read line; do ls -alh $line;done < file.txt
我发现它不能像我想的那样工作,支撑扩展在这种情况下不起作用,所以我想知道是否有工作或bash中的某些东西?
答案 0 :(得分:3)
Bash首先扩展大括号,然后扩展变量。这是一个更简单的例子:
$ a="/path/{a,b,c}"
$ echo $a
/path/{a,b,c}
$ eval 'echo $a'
/path/{a,b,c}
$ eval "echo $a"
/path/a /path/b /path/c
您需要使用eval强制执行第二次评估。
但是在使用eval时请仔细检查输入。你不希望有人在你的文件的某一行写下“虚拟; dobadthings”这样的东西......
答案 1 :(得分:2)
在这种特殊情况下,我根本不会使用大括号扩展。无论如何,这不是正确的工具。并且使其工作的唯一解决方法是以危险的方式使用eval
- 不仅因为潜在的恶意用户,而且仅仅因为文件名中可能会有一些特殊字符被这样做误解。
这项工作的正确工具是使用shell globs with pattern matching。
这可以让你走上正轨:
#!/bin/bash
shopt -s extglob
while IFS= read -r line; do
ls -alh -- $line
done < file.txt
将您的文件file.txt
写为:
/path/@(a|b|c)/file.d
/path/file.e
/path/file.f
您将能够以安全的方式使用*
,?
,角色类,+(...)
,!(...)
等精美内容