如何打开和关闭通配符?

如何打开和关闭通配符?

在我的~./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 | xcmd && 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。

你不能用 来做到这一点bashzsh在你可以做的地方使用:

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-scriptecho *

实际上,可能有一种方法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 +fset -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}

不是问题的直接答案,而是针对类似情况的有用的替代方法。

相关内容