コマンドラインプロンプトから次のコマンドを実行できます。
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-completion(bash-completion
少なくともDebianベースのオペレーティングシステムのパッケージにあります)via~/.bashrc
または/etc/bash.bashrc
whichを含むextglob
初期化時に有効。
これらの ksh スタイル拡張 glob 演算子は、ビルド時に bash ソースコードのスクリプト--disable-extended-glob
に渡すか 。configure
--enable-extended-glob-default
ただし、これはextglob
POSIX規則に違反していることに注意してください。たとえば、echo !(x)
POSIX言語sh
では動作が指定されていませんが、
a='!(x)'
echo $a
出力は、現在のディレクトリのファイル名のリストではなく!(x)
デフォルト値を想定する必要があります。ただし、次のように使用するビルドではこれを実行しないでください。 kshでは、これらの演算子はデフォルトで有効になっていますが、拡張時に認識されません。$IFS
x
bash
sh
X(...)
答え2
スクリプトの上部付近に次の行を追加します。
shopt -s extglob
!(...)
拡張パターンマッチング機能なので、extglob
使用するには有効化オプションが必要です。バラより内蔵店舗詳細については。