複数のファイル拡張子を繰り返す方法に関するさまざまなトピックを見ましたが、ほとんどの場合、リストは定義されています。
例:
for file in ${arg}/**/*.{txt,h,py}
do
....
done
ご覧のとおり、ファイル.TXT
は無視されます。残念ながら、この質問に答えた人はbash4でのみ機能すると言いました。しかし、私の設定ではbash3.xを使用します。
これを行う方法についてのアイデアはありますか?
答え1
bash
ここで以下を設定できますnocaseglob
。
shopt -s nocaseglob
for file in "$arg"/**/*.{txt,h,py}
do
....
done
shopt -u nocaseglob
noclaseglob
bash
2.01以降はすべてのバージョンで動作しますが、4.0以降が**
必要です(そして修正された4.3bash
までシンボリックリンクに従います)。スペースやワイルドカードを含めると問題が発生するため、引用bash
符を変更する必要があります。$arg
使用せずに**
次のことができます。
find "$arg" \( -iname '*.txt' -o -iname '*.h' -o -iname '*.py' \) -exec bash -c '
for file; do
...
done' bash {} +
その後、探しているすべてのファイルを見つけて別の引数として新しいbashインスタンスに渡し、そのファイルを繰り返します。各ファイル操作が単一のコマンドの場合は、新しいbashインスタンスをスキップしてコマンドを直接使用できます。
修正する
以下のStephaneのコメントによると、POSIX準拠のソリューションは次のとおりです。
find "$arg" \( -name '*.[tT][xX][tT]' -o -name '*.[hH]' -o -name '*.[pP][yY]' \) \
-exec sh -c '
for file do
...
done' sh {} +
答え2
代わりに使用してくださいzsh
:
setopt extendedglob
for f ($arg/**/*.(#i)(txt|h|py)(N.)) {
...
}
**/
: すべてのレベルのサブディレクトリ(#i)
残りのglob(たとえば~(i)
)に対して大文字と小文字を区別しない一致をオンにしますksh93
。(N.)
グローバル予選です。N
一致するファイルがない場合は、エラーを返さずに.
通常のファイル(find
sと同じ-type f
)を選択します。D
ドット(隠し)ファイルと一致するようにそこに1つを追加し、隠しディレクトリに移動できます(find
デフォルトと同じ)。
答え3
簡単なことはどうですか?
for file in "$(ls -1 | grep -iE '\.txt|\.py|\.h')";
do
....
done
別の簡単なオプションは次のとおりです。
find . -maxdepth 1 -iname '*.txt'; find . -maxdepth 1 -iname '*.py'; find . -maxdepth 1 -iname '*.h';
bashでは、findを$()角括弧で囲むことでリストを取得できます。