ファイル名の異常な文字を避けるには、「検索」を使用します。 -printf"%p\n"`

ファイル名の異常な文字を避けるには、「検索」を使用します。 -printf"%p\n"`

このfindコマンドのファイルパス

find . -printf "%p \n"

珍しい文字(スペース、バックスラッシュ、二重引用符など)をエスケープしないでください。

このオプションは-lsエスケープされたパスを印刷しますが。ls -dilsprintf

効率的なコマンドが必要なので、追加のコマンドを実行しても役に立たlsず、すべての追加文字を印刷することもできません。

エスケープされたパスを出力する他の(エレガントな)方法はありますかfind

答え1

find -exec通常、すべてのファイル名に対して実行されるコマンドを使用したり、find -print0NULLバイトで区切られたエントリを読み取ることができるいくつかのコマンド(たとえばxargs -0)に名前をパイプしたいとします。

本当に引用された文字列が必要な場合、Bashにはこれを行うためのいくつかのオプションがあります。

$ find -exec bash -c 'printf "%s\n" "${@@Q}"' sh {} +
'./single'\''quote'
'./space 1'
$'./new\nline'
'./double"quote'

$ find -exec bash -c 'printf "%q\n" "$@"' sh {} +
./single\'quote
./space\ 1
$'./new\nline'
./double\"quote

これにはシェルへの追加呼び出しが必要ですが、単一のexecで複数のファイル名を処理するために使用できます。


許可ビット(ACLではない)の保存に関しては、次のことができます(GNU findから):

find -printf "%#m:%p\0" > files-and-modes

これにより、権限、コロン、ファイル名、および nul バイトを含む項目が出力されます(例:)。そうだろう0644:name with spaces\0いいえ何でもエスケープして代わりにファイル名をそのまま印刷します(ただし、ターミナルに出力しない限り、この場合少なくとも改行がめちゃくちゃになります。)

Perlスクリプトを使用して結果を読み取ることができます。

perl -0 -ne '($m, $f) = split/:/, $_, 2; chmod oct($m), $f; ' < files-and-modes 

または Bash では、ほとんどの説明を参照してください。

while IFS=: read -r -d '' mode file ; do
    # do something useful
    printf "<%s> <%s>\n" "$mode" "$file"
    chmod "$mode" "$file"
done < files-and-modes

私がテストしたところによると、改行、引用符、スペース、コロンで動作します。IFS=" "名前に後にスペースが含まれていると、設定に従ってスペースが削除されるため、スペース以外のものを区切り文字として使用する必要があります。

答え2

これにより、zsh次のことができます。

print -r -- ./**/*(.D:q)

.同様に、willのような隠しファイルや-type f参照目的もD含まれます(-style参照を使用すると、これが期待する参照型かどうかはわかりません)。find:qzsh

様々なスタイルの引用を得ることができます。

$ print -r -- ./**/*(.D:q)
./$'\200' ./a\ b ./é ./\"foo\" ./It\'s\ bad ./$'\n'
$ files=(./**/*(.D))
$ print -r -- ${(q)files}
./$'\200' ./$'\n' ./a\ b ./é ./\"foo\" ./It\'s\ bad
$ print -r -- ${(qq)files}
'./�' './
' './a b' './é' './"foo"' './It'\''s bad'
$ print -r -- ${(qqq)files}
"./�" "./
" "./a b" "./é" "./\"foo\"" "./It's bad"
$ print -r -- ${(qqqq)files}
$'./\200' $'./\n' $'./a b' $'./é' $'./"foo"' $'./It\'s bad'

印刷できない \200 バイトに対してマイ端末エミュレータが表示するプレースホルダです。)

ここから回復可能な方法で権限を保存するには、次の手順を実行します。

find . -type f -printf '%m\0%p\0' > saved-permissions

復元するには(GNU仮定xargs):

xargs -r0n2 -a saved-permissions chmod

ただし、これはchmodファイルごとに1つの呼び出しを実行するため、非常に非効率的です。次のようにchmod組み込みシェルを使用できます。zshzmodload zsh/files

zmodload zsh/files
while IFS= read -rd '' mode && IFS= read -rd '' file; do
  chmod $mode $file
done < saved-permissions

答え3

より簡単な解決策を見つけました。

find -exec echo \'{}\' \;

これを使用して別のプログラムにパイプすることができます。

find -exec echo \'{}\' \; | xargs ls 

あるいは、echoの代わりに単にランダムなコマンドを使用して、任意の数の引数を追加することもできます。

find -exec mv \'{}\' somewhereelse \;

まずテストすることを忘れないでくださいecho

最後は動作しませんmvはファイルにアクセスする前に引用符を削除しませんので、代わりにパイプを使用してください。

find -exec echo mv \'{}\' somewhereelse \;| bash

答え4

なぜすべてのキャラクターを脱出しないのですか?その後、すべての操作(ls、rm、echoなど)で動作します。

find -name *.txt | sed -E 's/(.)/\\\1/g' | xargs ls

-exec(より効果的にするには、これをフォームに合わせて調整する必要があるかもしれません)

関連情報