Saya memiliki perintah find yang menemukan file dan direktori tertentu. Perintah find itu kemudian menjalankan rsync dengan file dan direktori yang ditemukan sebelumnya sebagai sumber. Masalahnya adalah file dan direktori tersebut dapat memiliki semua jenis karakter seperti tanda kutip tunggal dan ganda belum lagi karakter ilegal dari Windows dll…
Bagaimana saya bisa secara dinamis keluar dari string untuk digunakan dalam rsync atau perintah lain?
Perintah ini bekerja dengan mengkodekan tanda kutip ganda untuk string sumber rsync, tetapi akan rusak jika string memiliki tanda kutip ganda di dalamnya.
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}" \; \)
keluaran yang dihasilkan:
rsync -i -dIWRpEAXogt --numeric-ids --inplace --dry-run "test/this " is an issue" /mnt/backing
Perintah yang berfungsi setelah info dalam jawaban diterapkan:
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 {} \; \)
Jawaban yang Diterima:
Masalah kutipan Anda berasal dari Anda mencoba memecahkan masalah yang tidak Anda miliki. Kebutuhan untuk mengutip argumen hanya berperan saat Anda berurusan dengan shell, dan jika find
memanggil rsync
secara langsung, tidak ada shell yang terlibat. Menggunakan output visual bukanlah cara yang baik untuk mengetahui apakah itu berhasil atau tidak karena Anda tidak dapat melihat di mana setiap argumen dimulai dan diakhiri.
Inilah yang saya maksud:
# 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: -
Perhatikan bahwa saya tidak mengutip {}
di arg ke stat
.
Sekarang, perintah Anda akan menjadi sangat tidak berkinerja, karena Anda memanggil rsync
untuk setiap file yang cocok. Ada 2 cara untuk menyelesaikan ini.
Seperti yang telah ditunjukkan orang lain, Anda dapat menggunakan pipa daftar file ke rsync
di stdin:
# find . -type f -print0 | rsync --files-from=- -0 . dest/
# ls dest/
foo'"bar
Ini akan menggunakan byte nol sebagai pembatas nama file karena file tidak boleh berisi byte nol dalam namanya.
Terkait:Bagaimana cara memperbaiki kesalahan "Perangkat USB tidak dikenal membutuhkan lebih banyak daya daripada yang dapat dipasok Port"?
Jika Anda menggunakan GNU find
, Anda memiliki metode lain untuk memanggil -exec
, dan itu adalah -exec {} +
. Dalam gaya ini find
akan melewati lebih dari satu argumen pada suatu waktu. Namun semua argumen ditambahkan ke akhir perintah, bukan di tengah. Anda dapat mengatasinya dengan meneruskan argumen melalui shell kecil:
# find . -type f -exec sh -c 'rsync "[email protected]" dest/' {} +
# ls dest/
foo'"bar
Ini akan meneruskan daftar file ke sh
yang kemudian akan menggantikannya dengan "[email protected]"