154
for i in $(ls);do
    if [ $i = '*.java' ];then
        echo "I do something with the file $i"
    fi
done

現在のフォルダー内の各ファイルをループして、特定の拡張子と一致するかどうかを確認したい。上記のコードが機能しません。理由はわかりますか?

4

7 に答える 7

257

派手なトリックは必要ありません:

for i in *.java; do
    [ -f "$i" ] || break
    ...
done

ガードは、一致するファイルがない場合、存在しないファイル名を処理しようとせずにループが終了することを保証します*.java。(bashまたは同様のものをサポートするシェル) では、オプションを使用してnullglob、失敗した一致を単に無視し、ループの本体に入らないようにすることができます。

shopt -s nullglob
for i in *.java; do
    ...
done
于 2013-01-24T16:05:16.633 に答える
25

サブフォルダーを再帰的に追加し、

for i in `find . -name "*.java" -type f`; do
    echo "$i"
done
于 2014-10-09T09:14:47.427 に答える
14

正解は@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
于 2013-01-24T16:45:06.927 に答える
3

ファイルをループする正しい方法に関する他の回答に同意します。ただし、OPは尋ねました:

上記のコードは機能しません。理由はわかりますか?

はい!

優れた記事What is the difference between test, [ and [[ ?]は、他の違いの中でも、コマンド内でexpression matchingorを使用できないことを詳細に説明しています(これは の省略形です)pattern matchingtest[

機能 新しいテスト [[ 古いテスト [ 例

パターン マッチング = (または ==) (利用不可) [[ $name = a* ]] || echo "名前が 'a' で始まっていません: $name"

正規表現 =~ (利用不可) [[ $(date) =~ ^Fri\ ...\ 13 ]] && echo "13 日の金曜日です!"
マッチング

これがスクリプトが失敗する理由です。OPが構文を使用した回答に関心がある場合[[(コマンドほど多くのプラットフォームでサポートされていないという欠点があります[)、回答を編集してそれを含めることができます.

編集:回答のデータをテーブルとしてフォーマットする方法に関するヒントは役に立ちます!

于 2013-01-24T23:54:05.457 に答える
3

@chepner がコメントで述べているように、$i を固定文字列と比較しています。

状況を拡張して修正するには、正規表現演算子 =~ で [[ ]] を使用する必要があります

例えば:

for i in $(ls);do
    if [[ $i =~ .*\.java$ ]];then
        echo "I want to do something with the file $i"
    fi
done

=~ の右側の正規表現は、左側の演算子の値に対してテストされるため、引用符で囲む必要はありません (引用符で囲んだ場合はエラーにはなりませんが、固定文字列と比較されるため、失敗する可能性が高くなります。"

しかし、グロブを使用した上記の@chepnerの回答は、はるかに効率的なメカニズムです。

于 2013-01-24T16:42:42.220 に答える