私は現在、作成日の順序でディレクトリ内の特定のファイルを繰り返すようになっている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)
拡張時に分割+globが呼び出されます。
分割は$IFS
文字(デフォルトはSPC、TAB、およびNL)に基づいて行われ、glob部分は文字内のワイルドカードを検索し、そのパターンに一致するファイルを拡張しようとします。
ls
ここでは、実際にglob部分を実行せずにNL文字で出力を分割したいようです。したがって、次のようにする必要があります。
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
ここでは、glob修飾子を使用しているように((for)一致するファイルがない場合はエラーを回避するかのように)、*
現在のディレクトリから隠されていないすべてのファイルに展開され、期間に基づいて逆順にソートされます。ls -rt
Om
N
nullglob
またはGNUがある場合は、次のようにls
しますbash
。
eval "files=($(ls --quoting-style=shell-always -rt))"
for f in "${files[@]}"; do
printf '%s\n' "$f"
done