for i in $(ls);do
if [ $i = '*.Java' ];then
echo "I do something with the file $i"
fi
done
現在のフォルダー内の各ファイルをループし、特定の拡張子と一致するかどうかを確認します。上記のコードは機能しませんが、その理由はわかりますか?
派手なトリックは必要ありません:
for i in *.Java; do
[ -f "$i" ] || break
...
done
ガードは、一致するファイルがない場合、存在しないファイル名*.Java
を処理しようとせずにループが終了することを保証します。 bash
(または同様のものをサポートするシェル)では、nullglob
オプションを使用して、失敗した一致を単に無視し、ループの本体を入力することはできません。
shopt -s nullglob
for i in *.Java; do
...
done
正解は@chepnerの
EXT=Java
for i in *.${EXT}; do
...
done
ただし、ファイル名に特定の拡張子があるかどうかを確認するための小さなコツを次に示します。
EXT=Java
for i in *; do
if [ "${i}" != "${i%.${EXT}}" ];then
echo "I do something with the file $i"
fi
done
サブフォルダーを再帰的に追加し、
for i in `find . -name "*.Java" -type f`; do
echo "$i"
done
.img
、.bin
、.txt
サフィックスで終わるすべてのファイルをループし、ファイル名を出力します。
for i in *.img *.bin *.txt;
do
echo "$i"
done
または、再帰的な方法で(すべてのサブディレクトリでも検索):
for i in `find . -type f -name "*.img" -o -name "*.bin" -o -name "*.txt"`;
do
echo "$i"
done
@chepnerがコメントで述べているように、$ iを固定文字列と比較しています。
状況を拡張および修正するには、正規表現演算子=〜で[[]]を使用する必要があります
例えば:
for i in $(ls);do
if [[ $i =~ .*\.Java$ ]];then
echo "I want to do something with the file $i"
fi
done
=〜の右側の正規表現は、左辺演算子の値に対してテストされ、引用符で囲まれるべきではありません(引用符で囲まれたものはエラーになりませんが、固定文字列と比較されるため、失敗する可能性が高いです」
しかし、グロブを使用した上記の@chepnerの答えは、はるかに効率的なメカニズムです。
ファイルをループする正しい方法に関する他の回答に同意します。しかし、OPは尋ねました:
上記のコードは機能しませんが、その理由はわかりますか?
はい!
優れた記事 testと[[[?]]の違いは何ですか? では、test
コマンド内でexpression matching
またはpattern matching
を使用することはできないことを詳細に説明しています(これは[
の省略形です)
Feature new test [[old test [Example Pattern matching =(or ==)(not available)[[$ name = a *]] || echo "名前が 'a'で始まらない:$ name" 正規表現=〜(使用不可)[[$(date)=〜^ Fri\...\13] ] && echo "13日の金曜日です!" matching
これが、スクリプトが失敗する理由です。 OPが[[
構文([
コマンドほど多くのプラットフォームでサポートされていないというデメリットがある)の回答に興味がある場合は、回答を編集してそれを含めます。 。
編集:回答内のデータをテーブルとしてフォーマットする方法についてのヒントは参考になります!