特定のファイルとディレクトリを検索するfindコマンドがあります。次に、そのfindコマンドは、以前にソースとして見つかったファイルとディレクトリを使用してrsyncを実行します。問題は、これらのファイルとディレクトリに、Windowsなどの不正な文字は言うまでもなく、一重引用符や二重引用符など、あらゆる種類の文字を含めることができることです…
rsyncや他のコマンドで使用するために文字列を動的にエスケープするにはどうすればよいですか?
このコマンドは、rsyncソース文字列の二重引用符をハードコーディングすることで機能しますが、文字列に二重引用符が含まれていると壊れます。
find "/mnt/downloads/cache/" -depth -mindepth 1 \( \
-type f \! -exec fuser -s '{}' \; -o \
-type d \! -empty \) \
\( -exec echo rsync -i -dIWRpEAXogt --numeric-ids --inplace --dry-run '"{}"' "${POOL}" \; \)
結果の出力:
rsync -i -dIWRpEAXogt --numeric-ids --inplace --dry-run "test/this " is an issue" /mnt/backing
適用された回答の情報の後の作業コマンド:
find "/mnt/downloads/cache/" -depth -mindepth 1 \( \
-type f \! -exec fuser -s {} \; -o \
-type d \! -empty \) \
\( -exec rsync -i -dIWRpEAXogt --remove-source-files-- "${POOL} \; \) \
-o \( -type d -empty -exec rm -d {} \; \)
承認された回答:
見積もりの問題は、自分が持っていない問題を解決しようとしていることに起因しています。引数を引用する必要があるのは、シェルを扱っている場合、およびfind
の場合にのみ発生します。 rsync
を呼び出しています 直接、関係するシェルはありません。視覚的な出力を使用することは、各引数がどこから始まりどこで終わるかがわからないため、それが機能するかどうかを判断する良い方法ではありません。
意味は次のとおりです:
# touch "foo'\"bar"
# ls
foo'"bar
# find . -type f -exec stat {} \;
File: ‘./foo'"bar’
Size: 0 Blocks: 0 IO Block: 4096 regular empty file
Device: fd00h/64768d Inode: 1659137 Links: 1
Access: (0644/-rw-r--r--) Uid: ( 1004/ phemmer) Gid: ( 1004/ phemmer)
Access: 2017-12-09 13:21:28.742597483 -0500
Modify: 2017-12-09 13:21:28.742597483 -0500
Change: 2017-12-09 13:21:28.742597483 -0500
Birth: -
{}
を引用しなかったことに注意してください stat
への引数 。
そうは言っても、rsync
を呼び出しているため、コマンドのパフォーマンスは非常に低くなります。 一致するすべてのファイルに対して。これを解決する方法は2つあります。
他の人が示しているように、ファイルリストをrsync
にパイプすることができます stdin:
# find . -type f -print0 | rsync --files-from=- -0 . dest/
# ls dest/
foo'"bar
ファイルの名前にnullバイトを含めることはできないため、これはファイル名の区切り文字としてnullバイトを使用します。
関連:「不明なUSBデバイスはポートが供給できる以上の電力を必要とします」エラーを修正するにはどうすればよいですか?
GNU find
を使用している場合 、-exec
を呼び出す別の方法があります 、それは-exec {} +
。このスタイルではfind
一度に複数の引数を渡します。ただし、すべての引数はコマンドの途中ではなく、コマンドの最後に追加されます。小さなシェルに引数を渡すことでこれに対処できます:
# find . -type f -exec sh -c 'rsync "[email protected]" dest/' {} +
# ls dest/
foo'"bar
これにより、ファイルのリストがsh
に渡されます。 これにより、"[email protected]"
の代わりに使用されます