Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/bash/18.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Bash 通配符在shell中展开,但不在脚本中展开_Bash - Fatal编程技术网

Bash 通配符在shell中展开,但不在脚本中展开

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=“

因此,当我想使用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=“/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")
这与about
eval
一起提供。如果您提供以下图案:

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支架扩展。