bugfix> bash > 投稿

現在、ディレクトリ内のいくつかのファイルを作成日の順序でループすることになっているbashスクリプトを書いています。 そうするために私は使用します(の代わりに実際のコードで echo ):

for i in $(ls -tr)
do
    echo $i
done

これはほとんどの場合正常に機能します。

しかし今、私はスクリプトを壊すタイプのファイルを見つけました: aha_-_a ()a.txt

このファイル名には、空白とそれに続く開き括弧「(」が含まれています。これは改行をトリガーするようです。結果は次のとおりです。

aha_-_a
()a.txt

しかし、それは次のようになります。

aha_-_a ()a.txt

希望する動作を実現する方法を知っていますか?

回答 1 件
  • 去る $(ls -tr) 引用符で囲まれていない場合、展開時にsplit + globが呼び出されます。

    分割はの文字に基づいて行われます $IFS (デフォルトではSPC、TAB、NL)次に、globパーツはそこでワイルドカード文字を探し、対応するパターンに一致するファイルを展開しようとします。

    ここでは、実際にの出力を分割したいようです ls NL文字のみで、glob部分は実行しません。したがって、次のようになります。

    IFS=$'\n' # split on NL only
    set -o noglob # disable the glob part
    for f in $(ls -tr); do
      printf '%s\n' "$f"
    done
    
    

    これで、SPC文字を含むファイルで問題なく動作します。ただし、NL文字を含むファイル名がある場合は引き続き機能しません。

    ここでは、に切り替えるのが最善です zsh そして、やります:

    for f in *(NOm); do
      printf '%s\n' "$f"
    done
    
    

    どこ * 現在のディレクトリ内の非表示になっていないすべてのファイルに展開されます。 ls -rt で行います Om グロブ修飾子( N 1つ( nullglob )一致するファイルがない場合のエラーを回避します)。

    またはGNUをお持ちの場合 ls 、と bash

    eval "files=($(ls --quoting-style=shell-always -rt))"
    for f in "${files[@]}"; do
      printf '%s\n' "$f"
    done
    
    

あなたの答え