このfind
コマンドのファイルパス
find . -printf "%p \n"
珍しい文字(スペース、バックスラッシュ、二重引用符など)をエスケープしないでください。
このオプションは-ls
エスケープされたパスを印刷しますが。ls -dils
printf
効率的なコマンドが必要なので、追加のコマンドを実行しても役に立たls
ず、すべての追加文字を印刷することもできません。
エスケープされたパスを出力する他の(エレガントな)方法はありますかfind
?
答え1
find -exec
通常、すべてのファイル名に対して実行されるコマンドを使用したり、find -print0
NULLバイトで区切られたエントリを読み取ることができるいくつかのコマンド(たとえば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
:q
zsh
様々なスタイルの引用を得ることができます。
$ 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
組み込みシェルを使用できます。zsh
zmodload 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
(より効果的にするには、これをフォームに合わせて調整する必要があるかもしれません)