括弧は bash シェル自体では機能しますが、 bash スクリプトでは機能しません。

括弧は bash シェル自体では機能しますが、 bash スクリプトでは機能しません。

コマンドラインプロンプトから次のコマンドを実行できます。

cp -r folder/!(exclude-me) ./

すべてを再帰的にコピーfolder とは別にexclude-me現在のディレクトリ内の名前付きサブディレクトリです。これは予想通り正確に機能します。しかし、私が書いたbashスクリプトで動作するには、次のものが必要です。

if [ -d "folder" ]; then
  cp -r folder/!(exclude-me) ./
  rm -rf folder
fi

しかし、スクリプトを実行すると、次のようになります。

bash my-script.sh

わかりました:

my-script.sh: line 30: syntax error near unexpected token `('
my-script.sh: line 30: `  cp -r folder/!(exclude-me) ./'

コマンドプロンプトで動作する理由はわかりませんが、bashスクリプトでは同じ行が機能しません。

ベストアンサー1

これは、使用する構文がアクティブでない特定の bash 機能によって異なります。スクリプトに関連コマンドを追加してアクティブにすることができます。

## Enable extended globbing features
shopt -s extglob

if [ -d "folder" ]; then
  cp -r folder/!(exclude-me) ./ &&
    rm -rf folder
fi

これは以下に関連する部分ですman bash

  If the extglob shell option is enabled using the shopt builtin, several
  extended  pattern  matching operators are recognized.  In the following
  description, a pattern-list is a list of one or more patterns separated
  by a |.  Composite patterns may be formed using one or more of the fol‐
  lowing sub-patterns:

         ?(pattern-list)
                Matches zero or one occurrence of the given patterns
         *(pattern-list)
                Matches zero or more occurrences of the given patterns
         +(pattern-list)
                Matches one or more occurrences of the given patterns
         @(pattern-list)
                Matches one of the given patterns
         !(pattern-list)
                Matches anything except one of the given patterns

あなたの場合、bashの対話型呼び出しでこれを有効にする理由は、おそらくあなたが持っているかshopt -s extglob使用し~/.bashrcているからです。https://github.com/scop/bash-completionbash-completion少なくともDebianベースのオペレーティングシステムのパッケージにあります)via~/.bashrcまたは/etc/bash.bashrcwhichを含むextglob初期化時に有効

これらの ksh スタイル拡張 glob 演算子は、ビルド時に bash ソースコードのスクリプト--disable-extended-globに渡すか 。configure--enable-extended-glob-default

ただし、これはextglobPOSIX規則に違反していることに注意してください。たとえば、echo !(x)POSIX言語shでは動作が指定されていませんが、

a='!(x)'
echo $a

出力は、現在のディレクトリのファイル名のリストではなく!(x)デフォルト値を想定する必要があります。ただし、次のように使用するビルドではこれを実行しないでください。 kshでは、これらの演算子はデフォルトで有効になっていますが、拡張時に認識されません。$IFSxbashshX(...)

おすすめ記事