在我的~./bashrc
别名中,我已经不再像这样进行通配了。
alias x='set -f;. any.sh'
但是哪个命令再次启用通配符或者我应该在中设置此选项any.sh
?
欢迎任何回应。
答案1
any.sh
如果您希望仅在 shell 解释基于、 withbash4.4+
或- 的 shell中的代码时禁用 glob ash
,您可以执行以下操作:
x() {
local -
set -o noglob
. any.sh
}
或者在zsh
:
x() {
set -o localoptions -o noglob
. any.sh
}
也就是说,使用函数而不是别名(您不想对多个命令使用别名,因为当您这样做时,这不会做您想要的事情cmd | x
)cmd && x
,确保对选项进行更改($-
作为一种方式对变量进行更改)查看它)是函数本地的,禁用 glob 并获取文件。
使用旧版本的bash
,您可以执行以下操作:
x() {
local ret restore
[[ $- = *f* ]] || restore='set +o noglob'
set -o noglob
. any.sh
ret=$?
eval "$restore"
return "$ret"
}
或者也许是更通用的辅助函数,例如:
withopt() {
local ret option
local -a restore
option=$1; shift
[[ -o $option ]] || restore=(set +o "$option")
set -o "$option"
"$@"
ret=$?
"${restore[@]}"
return "$ret"
}
然后,如果您愿意,可以使用别名:
alias x='withopt noglob . any.sh'
请注意,如果您这样做,它不会阻止*
扩展:
x *
因为该noglob
选项在该命令被评估很久之后才最终被启用。为此,请参阅我的另一个答案(对不同问题的回答)。
答案2
这是在问题澄清之前发布的,现在解决了不同的需求。我仍然把它留在这里,因为这对其他人可能有用。
我想你希望能够做到:
x *.txt
以及*.txt
要传递的未展开的any.sh
和随后重新启用的 glob。
你不能用 来做到这一点bash
。zsh
在你可以做的地方使用:
alias x='noglob any.sh`
其中noglob
仅禁用该命令的别名。
$ echo /etc/p*d
/etc/pam.d /etc/passwd /etc/profile.d
$ noglob echo /etc/p*d
/etc/p*d
echo
请注意,它仅影响该命令参数中的 glob 扩展。*
仍会在noglob echo $(echo *)
ornoglob eval 'echo *'
或 的位置noglob . some-script
进行扩展。some-script
echo *
实际上,可能有一种方法bash
:
oneshot_noglob() {
case $- in
(*f*) ;; # globs already disabled
(*) set -f; shot=0; debug_trap=$(trap -p DEBUG)
trap '
if ((++shot == 2)); then
set +f
trap - DEBUG
'"$debug_trap"'
fi' DEBUG;;
esac
}
alias x='oneshot_noglob; any.sh'
它使用 DEBUG 陷阱set +f
在set -f
.
现在,对于包含多个命令的所有别名,有一些注意事项。
echo foo | x
变成:
echo foo | oneshort_noglob; any.sh
因此 的输出echo
仅馈送到oneshort_noglob
。
对于类似的事情也是如此:
cmd && x
any.sh
无论cmd
成功与否都会执行到哪里。
另请注意,它会影响每个级别的子 shell 中的所有 glob,直到在主 shell 进程中执行第二个命令之前。
例如,在 中x $(echo *; echo *) *
,这些*
都不会被扩展,因为除非设置该extdebug
选项,否则 DEBUG 陷阱不会被继承。
答案3
人们可能会暂时改变某些东西,然后尝试将其恢复到之前的状态。但我提出更好、更干净、更可靠、更易于维护的方法:只需在本地进行所需的更改。
Bash
允许您通过使用轻松实现这一点子外壳(更多信息在这里 -分组命令)。
在你的情况下,可以这样做
alias x='( set -f;. any.sh ; )'
答案4
在尝试了几种设置后,我没有让 glob 在 bash shell 脚本中工作。相反,我在 CLI 中放置了一个 glob,并且按预期工作。
由于这不起作用:
sh ./test.sh file ls "${1}*.ppm"
将其替换为:
sh ./test.sh file f*.ppm ls ${2}
不是问题的直接答案,而是针对类似情况的有用的替代方法。