for-doループは、スペースを含むファイル名では機能しません。

for-doループは、スペースを含むファイル名では機能しません。
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. 1whileループを使用すると、空白のあるファイルを問題なく処理できます。

$ 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とは異なり、移植可能であり、任意のファイル名を非常によく処理する-execfindを使用することです。-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

関連情報