Bashスクリプトを学びながら、forループに入れ子になったgrepを使用して結果をフィルタリングしようとしています。
sample filenames:
this-file_AAC.txt
this-other_file_AAAC.txt
yep-a-file_AAC.nfo
oops_another_one.reamde
スクリプトは次のとおりです。
shopt -s globstar nullglob dotglob
for file in ./**/*.{txt,reamde,nfo}; do
printf "input: ${file}\n"
if grep -qF _AAC $file; then
printf "output: ${file}\n"
# do stuff with $file
fi
done
この特別な場合は、含まれているすべてのファイル_AAC
にジョブが適用され、結果が正しいことを確認するために標準出力に印刷するだけです。
問題は、どんなものもif
文を超えることができないということです。それで私が知らないことが抜けましたね。働く唯一の事はこのprintf "input...
減少です。
私は何を見逃していますか?
答え1
最後のファイル名部分に名前が付けられたすべてのファイルを一致させるには、.../something_AACxyz
その部分をglobパターン/ワイルドカードに直接追加します。_AAC
_AAC
for file in ./**/*_AAC*.{txt,reamde,nfo}; do
_AAC
ファイル名を任意の部分に表示するには、Bashで次のようにします。
for file in ./**/*.{txt,reamde,nfo}; do
if [[ $file == *_AAC* ]]; then
echo "'$file' contains _AAC"
else
echo "'$file' has NO _AAC"
fi
done
ここでは、globと一致するファイルも取得できますが_AAC
。
とにかく、Bashでは中括弧拡張を使用する代わりにパターンを有効にして上書きextglob
することもできます。@(...|...)
for file in ./**/*_AAC*.@(txt|reamde|nfo); do
中かっこ拡張は@(..)
単一のglobですが、複数の異なるglobを作成します。 (つまり、*.{foo,bar}
と同じ*.foo *.bar
)nullglob
setを使用するときに一致しない項目は重要ではありませんが、setを使用するとfailglob
一致しない項目が1つしかない場合でもコマンド全体が失敗します。
答え2
あなたのスクリプトは次のように言います:
if grep -qF _AAC $file; then
これは、「指定されたファイルの内容に$file
リテラル文字列が含まれている場合_AAC
...」ブロックの内容を実行することを意味しますthen
。
_AAC
変数拡張で生成された文字列内で検索するには($file
例:_AACがファイル名自体に表示されることを確認する)、次のように記述する必要がbash
あります。
if grep -qF _AAC <<< "$file"; then
あるいは、@roaimaが指摘したように、検索中のリテラル文字列をワイルドカードファイル仕様に含めることもできます。