for X in $(find ~/Documents/ -type f);do date -r "${X}";done
上記の行は、「/Documents/」のファイル名にスペースが含まれていない場合は正しく機能します。
ただし、ファイル名にスペースが含まれている場合は、次のエラーが表示されます。
No such file or directory
スペースを含むファイル名に対してどのように機能させることができますか?
答え1
ループを使用しないで、-exec
次のパラメータを使用してくださいfind
。
find ~/Documents/ -type f -exec date -r {} \;
答え2
はい。これはfind
、andループを使用する際のよく知られた問題の1つです。
この問題を解決する簡単な方法は、見つかったリストをstdoutにダンプすることですread
。
find ~/Documents/ -type f |
while IFS= read -r filename
do
date -r "$filename" # ... or any other command using $filename
done
コマンドが十分に小さい場合は、-exec
次のキーを使用できますfind
。
find ~/Documents/ -type f -exec date -r '{}' \;
答え3
for
そうすることはできません。これがファイル名を返すコマンドの出力を繰り返すためにこの方法を使用しない理由の1つです。また〜として知られていますバッシュトラップNo. 1。while
ループを使用すると、空白のあるファイルを問題なく処理できます。
$ ls
'a file with spaces'
$ find . -type f | while read -r X; do date -r "$X"; done
Fri May 12 04:51:42 PM BST 2023
ただし、改行文字を含むファイル名はまだ失敗します。
$ touch "$(printf 'a file with\na newline')"
$ ls
'a file with'$'\n''a newline' 'a file with spaces'
$ find . -type f | while read -r X; do date -r "$X"; done
date: './a file with': No such file or directory
date: 'a newline': No such file or directory
Fri May 12 04:51:42 PM BST 2023
この問題を解決するには、実装がこれをサポートしていると仮定し、nullで終わる行を印刷してから、NULバイトを区切り文字として使用するループをfind
使用できます。-print0
このように:
$ find . -type f -print0 | while IFS= read -r -d '' X; do date -r "$X"; done
Fri May 12 04:53:06 PM BST 2023
Fri May 12 04:51:42 PM BST 2023
つまり、これまでの最善の方法は、POSIXとは異なり、移植可能であり、任意のファイル名を非常によく処理する-exec
findを使用することです。-print0
$ find . -type f -exec date -r {} \;
Fri May 12 04:53:06 PM BST 2023
Fri May 12 04:51:42 PM BST 2023