web-dev-qa-db-ja.com

グロビングをオンまたはオフにする方法は?

エイリアスの~./bashrc内で、このようにグロビングを無効にしました。

alias x='set -f;. any.sh'

しかし、どのコマンドが再度グロビングを有効にするか、このオプションをany.shに設定する必要がありますか?

どんな反応でも大歓迎です。

5
John Goofy

シェルがany.shのコードをbash4.4+またはashベースのシェルで解釈しているときにのみグロブを無効にする場合は、次のようにできます。

x() {
  local -
  set -o noglob
  . any.sh
}

またはzsh内:

x() {
  set -o localoptions -o noglob
  . any.sh
}

つまり、エイリアスの代わりに関数を使用します(たとえば、cmd | xまたはcmd && xを実行するときに、エイリアスが必要な機能を実行しないため、いくつかのコマンドにエイリアスを使用したくない)。オプションへの変更(それを見る1つの方法として$-変数への変更)は関数に対してローカルであり、グロブを無効にしてファイルをソースします。

古いバージョンの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オプションは、コマンドが評価されてからかなり後に有効になるため、それについては、 他の答え (別の質問に対する答え)を参照してください。

10

これは、質問が明確になる前に投稿され、現在は別のニーズに対応しています。他の人に役立つので、私はまだここに残しています。

あなたができるようになりたいと思います:

_x *.txt
_

_*.txt_は展開されずに_any.sh_に渡され、グロブは後で再度有効になります。

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コマンドの引数のグロブの展開にのみ影響することに注意してください。 _*_は引き続きnoglob echo $(echo *)または_noglob 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_の後に1つのコマンドが実行された後、_set -f_を復元します。

現在、複数のコマンドを含むすべてのエイリアスがあるため、いくつかの注意点があります。

_echo foo | x
_

になる:

_echo foo | oneshort_noglob; any.sh
_

したがって、echoの出力は_oneshort_noglob_にのみ送られます。

同じようなもの:

_cmd && x
_

cmdが成功したかどうかに関係なく、_any.sh_が実行される場所。

また、メインシェルプロセスで2番目のコマンドが実行される直前まで、サブシェルのすべてのレベルのすべてのグロブに影響することにも注意してください。

たとえば、x $(echo *; echo *) *では、extdebugオプションを設定しない限りDEBUGトラップが継承されないため、これらの_*_は拡張されません。

4