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
サブフォルダーを再帰的に追加し、
for i in `find . -name "*.java" -type f`; do
echo "$i"
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
ファイルをループする正しい方法に関する他の回答に同意します。ただし、OPは尋ねました:
上記のコードは機能しません。理由はわかりますか?
はい!
優れた記事What is the difference between test, [ and [[ ?]は、他の違いの中でも、コマンド内でexpression matching
orを使用できないことを詳細に説明しています(これは の省略形です)pattern matching
test
[
機能 新しいテスト [[ 古いテスト [ 例 パターン マッチング = (または ==) (利用不可) [[ $name = a* ]] || echo "名前が 'a' で始まっていません: $name" 正規表現 =~ (利用不可) [[ $(date) =~ ^Fri\ ...\ 13 ]] && echo "13 日の金曜日です!" マッチング
これがスクリプトが失敗する理由です。OPが構文を使用した回答に関心がある場合[[
(コマンドほど多くのプラットフォームでサポートされていないという欠点があります[
)、回答を編集してそれを含めることができます.
編集:回答のデータをテーブルとしてフォーマットする方法に関するヒントは役に立ちます!
@chepner がコメントで述べているように、$i を固定文字列と比較しています。
状況を拡張して修正するには、正規表現演算子 =~ で [[ ]] を使用する必要があります
例えば:
for i in $(ls);do
if [[ $i =~ .*\.java$ ]];then
echo "I want to do something with the file $i"
fi
done
=~ の右側の正規表現は、左側の演算子の値に対してテストされるため、引用符で囲む必要はありません (引用符で囲んだ場合はエラーにはなりませんが、固定文字列と比較されるため、失敗する可能性が高くなります。"
しかし、グロブを使用した上記の@chepnerの回答は、はるかに効率的なメカニズムです。