Bash 通配符在shell中展开,但不在脚本中展开
因此,当我想使用bash列出以多个字母开头的文件时,我可以执行类似于Bash 通配符在shell中展开,但不在脚本中展开,bash,Bash,因此,当我想使用bash列出以多个字母开头的文件时,我可以执行类似于echo/home/username/{A,B,C}*的操作,正确地回显以A,B,C开头的文件名 我正试图对脚本中包含用户输入的bash变量执行相同的操作,比如说脚本名为run\u user\u input.sh): var=$1;echo$var 我以/run\u user\u input.sh”/home/username/{A,B}*“的形式运行它 但这只是呼应/home/username/{A,B}* 请注意,var=“
echo/home/username/{A,B,C}*
的操作,正确地回显以A
,B
,C
开头的文件名
我正试图对脚本中包含用户输入的bash变量执行相同的操作,比如说脚本名为run\u user\u input.sh
):var=$1;echo$var代码>
我以/run\u user\u input.sh”/home/username/{A,B}*“
的形式运行它
但这只是呼应/home/username/{A,B}*
请注意,var=“/home/username/A*”;echo$var代码>仍能正常工作
如何解决这个问题呢?在双引号中,只展开了一些内容:最重要的是参数和命令替换,但没有文件名(也没有大括号展开),因此双引号中的*
始终是文字
然后,在赋值的右侧,也没有文件名和大括号扩展,因此var=*
将把一个文本*
放入var
,即使没有引号。您的上一个示例之所以“有效”,是因为您没有引用$var
的扩展,但它确实包含/home/username/A*
方法是使用数组:
fnames=(/home/username/{A,B,C}*)
这将执行大括号和文件名扩展,数组元素将分别包含一个文件名,正确转义空格和全局字符。使用适当的报价访问它们:
echo "${fnames[0]}"
例如,提供第一个文件名
如果将模式作为参数提供给脚本,则可能无法使用eval
:
pattern=$1
eval fnames=("$pattern")
这与abouteval
一起提供。如果您提供以下图案:
pattern='x); echo pwnd #'
eval
将行扩展到
fnames=(x); echo pwnd #)
并实际运行注入的命令,这可能比一个echo更不友好
不幸的是,鲁棒性方法
eval "$(printf 'fnames=(%q)' "$pattern")"
不起作用,因为它会阻止扩展
为了避免这种情况,我建议重写脚本以接受多个参数,并让shell进行扩展:
./yourscript path/to/dir/{A,B}*
在剧本中,类似于
for file; do <something>; done
用于文件;做完成
(这与“$@;do;done”中文件的相同。现在,您有了由shell处理扩展的好处,没有了eval
的缺点。值得注意的是,括号扩展不会对参数扩展的结果执行,并且bash
显示了其处理不匹配模式的默认行为(由于未展开的大括号,此处不匹配)作为文本字符串。问题是我的脚本将“/home/username/{a,B,C}*”
作为可自定义的用户输入。因此它用作echo$1
其中$1==“/home/username/{a,B,C}*”
-我应该更清楚地说明这一点。上面的解决方案无法直接使用这样的输入,对吗?@tangy类似于此问题?@tangy您需要更新问题,确切说明您的脚本是如何接收该输入的。@tangy如果您想评估用户输入,您可能需要eval
ns支架扩展。