スペースを含むリストを繰り返すには?

スペースを含むリストを繰り返すには?

場合によっては、スペースを含むリストを繰り返す必要があります。

これが私が今使っているスクリプトです

locate .txt > list

for book in $(cat list)
do
    cp "${book}" /mnt/e/BOOK
done

次に、すべての.txtファイルを指定されたディレクトリにコピーする必要があります。私のリストに以下が含まれている場合は問題ありません。

/mnt/d/txtfiles/mytextfile1.txt

ただし、スクリプトが繰り返されると、次のようになります。

/mnt/d/txtfiles/My text . File2.txt

空白のため、リストファイルパスが1行にある間に繰り返すのに問題があります。

ベストアンサー1

任意のファイル名を処理するには、ファイルパスには表示できないバイトでリストを区切る必要があります。動作する唯一のものはバイト0です。

GNUツールを想定すると:

locate -0 '*.txt' |
  xargs -r0 cp -it /mnt/e/BOOK

または以下を使用してzsh

cp -i ${(0)"$(locate -0 '*.txt')"} /mnt/e/BOOK/

(ただし、この方法とは異なり、xargsファイルのリストが大きすぎると失敗する可能性があるため、複数の呼び出しを実行して問題を解決できます。一致するファイルがない場合はxargsエラー情報も表示されます。)cp

0行ではなくNULで区切られたレコードで機能するこれらのオプションまたはパラメータ拡張フラグは、ファイルパスのリストを処理するように特別に設計されています。

テキスト行(* nixでは、限られた数の文字(バイトではない)で構成される改行で区切られたシーケンス)は通常ファイルパスに保存できません。これは、ファイルパスがテキストであることを保証できず、改行が含まれる可能性があるためです。

Yoursは$(cat list)リストのコンテキストで引用されていないコマンド置換であるため、ほとんどのBourneと同じシェルでIFS-split + globを経験しますがzsh

ここlocateでは、NULで区切られたレコードを含むlocate -0ようにリストを変更しlist、NULに分割されるようにIFS分割を調整してアクティブにglobなっていないことを確認する必要があります。

ただし、これは他のシェルがその変数へのNUL保存をサポートしていない場合にのみ機能しますIFS=$'\0'が、上記のパラメータ拡張フラグ(明示的な分割演算子)を使用することはグローバルに変更するよりもはるかに優れています。zshzsh0IFS

シェル4.4以降では、bash代替は次のとおりです。

locate -0 '*.txt' > list &&
  readarray -td '' list < list &&
  cp -i "${list[@]}" /mnt/w/book

またはlistファイルブローカーなしで:

readarray -td '' list < <(locate -0 '*.txt') &&
  cp -i "${list[@]}" /mnt/w/book

locate .txtまた、これはパス内のすべての項目を返すことに注意してください。たとえば、これにはを.txt含めることができます。そのパスのみが返されます。/foo.txting/bar.mp4locate '*.txt'終わり存在する.txt。たとえば、ファイルを含め続けたいが、.txt.gzフルパスではなくファイル名のみを確認したい場合。.txt.in.txtlocate -0 -b .txt

おすすめ記事