Saya mencoba untuk menyalin banyak file di bawah direktori dan sejumlah file memiliki spasi dan tanda kutip tunggal dalam namanya. Ketika saya mencoba untuk string bersama find
dan grep
dengan xargs
, saya mendapatkan error berikut:
find .|grep "FooBar"|xargs -I{} cp "{}" ~/foo/bar
xargs: unterminated quote
Adakah saran untuk penggunaan xarg yang lebih kuat?
Ini ada di Mac OS X 10.5.3 (Leopard) dengan BSD xargs
.
--delimiter
opsi (-d
). Cobalah dengan\n
sebagai pembatas, ini mencegahxargs
memisahkan garis dengan spasi menjadi beberapa kata / argumen.Jawaban:
Anda dapat menggabungkan semua itu menjadi satu
find
perintah:Ini akan menangani nama file dan direktori dengan spasi di dalamnya. Anda dapat menggunakan
-name
untuk mendapatkan hasil case-sensitive.Catatan:
--
Bendera berlalu untukcp
mencegahnya memproses file yang dimulai dengan-
sebagai opsi.sumber
xargs
tidak diperlukan untuk mengatasi masalah yang Anda gambarkan,find
sudah mendukungnya dengan-exec
+
tanda baca.find . -print0 | grep --null 'FooBar' | xargs -0 ...
Saya tidak tahu apakah
grep
mendukung--null
, atauxargs
mendukung-0
, di Leopard, tetapi di GNU itu semua baik.sumber
grep -{z|Z}
berarti "berperilaku sebagai zgrep" (dekompresi) dan tidak dimaksudkan "mencetak byte nol setelah setiap nama file". Gunakangrep --null
untuk mencapai yang terakhir.find . -name 'FooBar' -print0 | xargs -0 ...
?-name
atau-path
berfungsi dengan baik. OP telah menentukan penggunaangrep
, mungkin karena mereka ingin memfilter daftar menggunakan ekspresi reguler.xargs -0
dalam hubungannya denganfind -print0
. Yang terakhir mencetak nama file dengan terminator NUL dan mantan menerima file seperti itu. Mengapa? Nama file di Unix dapat berisi karakter baris baru. Tetapi mereka tidak dapat berisi karakter NUL.Cara termudah untuk melakukan apa yang diinginkan oleh poster asli adalah mengubah pembatas dari spasi putih menjadi hanya karakter end-of-line seperti ini:
sumber
sed -e 's_\(.*\)_"\1"_g'
xargs
.xargs: illegal option -- d
Ini lebih efisien karena tidak menjalankan "cp" beberapa kali:
sumber
Saya mengalami masalah yang sama. Inilah cara saya menyelesaikannya:
Saya biasa
sed
mengganti setiap baris input dengan baris yang sama, tetapi dikelilingi oleh tanda kutip ganda. Darised
halaman manual, " ... Sebuah ampersand (` `& '') yang muncul pada penggantian diganti dengan string yang cocok dengan RE ... " - dalam hal ini,,.*
seluruh baris.Ini menyelesaikan
xargs: unterminated quote
kesalahan.sumber
sed s/.*/\"&\"/
untuk membuatnya bekerja."
in - kecuali sed juga mengutip harga?sed
jenius dan untuk saat ini solusi yang tepat tanpa menulis ulang masalahnya!Metode ini berfungsi pada Mac OS X v10.7.5 (Lion):
Saya juga menguji sintaks yang tepat yang Anda posting. Itu juga bekerja dengan baik pada 10.7.5.
sumber
-I
tersirat-L 1
(demikian kata manual), yang berarti perintah cp sedang dijalankan sekali per file = v lambat.find ... -print0
danxargs -0
bekerja di sekitar xargs "dengan kutipan default adalah khusus". Kedua, umumnya menggunakan'{}'
tidak{}
dalam perintah yang dikirimkan ke xargs, untuk melindungi terhadap spasi dan karakter khusus.Hanya saja, jangan gunakan
xargs
. Ini adalah program yang rapi tetapi tidak berjalan dengan baikfind
ketika dihadapkan dengan kasus-kasus yang tidak sepele.Berikut ini adalah solusi portabel (POSIX), yaitu solusi yang tidak memerlukan
find
,xargs
ataucp
ekstensi spesifik GNU:Catat akhirnya
+
bukan yang lebih biasa;
.Solusi ini:
menangani file dan direktori dengan benar dengan ruang yang disematkan, baris baru, atau karakter eksotis apa pun.
bekerja pada sistem Unix dan Linux apa pun, bahkan yang tidak menyediakan toolkit GNU.
tidak menggunakan program
xargs
mana yang bagus dan bermanfaat, tetapi membutuhkan terlalu banyak penyesuaian dan fitur non-standar untuk menanganifind
keluaran dengan benar .juga lebih efisien (baca lebih cepat ) daripada yang diterima dan sebagian besar jika tidak semua jawaban lainnya.
Perhatikan juga bahwa meskipun apa yang dinyatakan dalam balasan atau komentar lain mengutip
{}
tidak berguna (kecuali jika Anda menggunakanfish
shell eksotis ).sumber
find
dapat melakukan apaxargs
tanpa overhead.Lihatlah ke dalam menggunakan opsi --null commandline untuk xargs dengan opsi -print0 di find.
sumber
Bagi mereka yang bergantung pada perintah, selain menemukan, misalnya
ls
:sumber
-I
menyiratkan-L 1
Saya percaya bahwa ini akan bekerja dengan andal untuk karakter apa pun kecuali umpan baris (dan saya menduga bahwa jika Anda mendapat umpan baris di nama file Anda, maka Anda memiliki masalah yang lebih buruk dari ini). Itu tidak memerlukan GNU findutils, hanya Perl, jadi itu harus bekerja cukup banyak di mana saja.
sumber
mkdir test && cd test && perl -e 'open $fh, ">", "this-file-contains-a-\n-here"' && ls | od -tx1
|perl -lne 'print quotemeta'
persis apa yang saya cari. Posting lain di sini tidak membantu saya karenafind
saya harus menggunakangrep -rl
untuk mengurangi jumlah file PHP menjadi hanya yang terinfeksi malware.Saya telah menemukan bahwa sintaks berikut bekerja dengan baik untuk saya.
Dalam contoh ini, saya mencari 200 file terbesar lebih dari 1.000.000 byte di sistem file yang dipasang di "/ usr / pcapps".
Baris-liner Perl antara "find" dan "xargs" lolos / mengutip setiap blank sehingga "xargs" meneruskan setiap nama file dengan blanko yang tertanam ke "ls" sebagai argumen tunggal.
sumber
Bingkai tantangan - Anda bertanya bagaimana menggunakan xargs. Jawabannya adalah: Anda tidak menggunakan xargs, karena Anda tidak membutuhkannya.
The komentar oleh
user80168
menggambarkan cara untuk melakukan hal ini langsung dengan cp, tanpa menyebut cp untuk setiap file:Ini berfungsi karena:
cp -t
bendera memungkinkan untuk memberikan target direktori dekat awalcp
, daripada mendekati akhir. Dariman cp
:The
--
bendera mengatakancp
untuk menafsirkan semuanya setelah sebagai nama file, bukan bendera, sehingga file yang dimulai dengan-
atau--
tidak membingungkancp
; Anda masih memerlukan ini karena-
/--
karakter ditafsirkan olehcp
, sedangkan karakter khusus lainnya ditafsirkan oleh shell.The
find -exec command {} +
varian dasarnya melakukan hal yang sama seperti xargs. Dariman find
:Dengan menggunakan ini dalam find secara langsung, ini menghindari kebutuhan pipa atau doa shell, sehingga Anda tidak perlu khawatir tentang karakter jahat dalam nama file.
sumber
Ketahuilah bahwa sebagian besar opsi yang dibahas dalam jawaban lain tidak standar pada platform yang tidak menggunakan utilitas GNU (Solaris, AIX, HP-UX, misalnya). Lihat spesifikasi POSIX untuk perilaku xarg 'standar'.
Saya juga menemukan perilaku xargs di mana ia menjalankan perintah setidaknya sekali, bahkan tanpa input, menjadi gangguan.
Saya menulis versi pribadi saya sendiri xargs (xargl) untuk menangani masalah spasi dalam nama (hanya baris baru terpisah - meskipun kombinasi 'find ... -print0' dan 'xargs -0' cukup rapi mengingat nama file tidak dapat mengandung karakter ASCII NUL '\ 0'. xargl saya tidak selengkap yang dibutuhkan untuk diterbitkan - terutama karena GNU memiliki fasilitas yang setidaknya sama baiknya.
sumber
find
tidak perluxargs
di tempat pertama (dan itu sudah benar 11 tahun yang lalu).Dengan Bash (bukan POSIX) Anda bisa menggunakan proses substitusi untuk mendapatkan baris saat ini di dalam variabel. Ini memungkinkan Anda menggunakan kutipan untuk keluar dari karakter khusus:
sumber
Bagi saya, saya mencoba melakukan sesuatu yang sedikit berbeda. Saya ingin menyalin file .txt saya ke folder tmp saya. Nama file .txt berisi spasi dan karakter tanda kutip. Ini berfungsi pada Mac saya.
sumber
Jika versi find dan xarg pada sistem Anda tidak mendukung
-print0
dan-0
beralih (misalnya find dan xarg AIX), Anda dapat menggunakan kode yang sangat kelihatan ini:Di sini sed akan mengurus pelarian ruang dan mengutip untuk xargs.
Diuji pada AIX 5.3
sumber
Saya membuat skrip pembungkus portabel kecil yang disebut "xargsL" di sekitar "xargs" yang membahas sebagian besar masalah.
Berlawanan dengan xargs, xargsL menerima satu pathname per baris. Nama path dapat berisi karakter apa pun kecuali (jelas) baris baru atau byte NUL.
Kutipan tidak diperbolehkan atau didukung dalam daftar file - nama file Anda dapat berisi semua jenis spasi putih, backslash, backticks, karakter wildcard shell dan sejenisnya - xargsL akan memprosesnya sebagai karakter literal, tidak ada salahnya dilakukan.
Sebagai fitur bonus tambahan, xargsL tidak akan menjalankan perintah sekali jika tidak ada input!
Perhatikan perbedaannya:
Setiap argumen yang diberikan kepada xargsL akan diteruskan ke xargs.
Berikut ini skrip shell POSIX "xargsL":
Masukkan skrip ke beberapa direktori di $ PATH Anda dan jangan lupa
$ chmod +x xargsL
skrip di sana untuk membuatnya dapat dieksekusi.
sumber
Versi Perl bill_starr tidak akan bekerja dengan baik untuk baris baru yang disematkan (hanya berupaya dengan spasi). Bagi mereka yang menggunakan Solaris misalnya di mana Anda tidak memiliki alat GNU, versi yang lebih lengkap mungkin (menggunakan sed) ...
sesuaikan find dan grep argumen atau perintah lain seperti yang Anda butuhkan, tetapi sed akan memperbaiki baris / spasi / tab baru Anda.
sumber
Saya menggunakan jawaban Bill Star yang sedikit dimodifikasi pada Solaris:
Ini akan menempatkan tanda kutip di sekitar setiap baris. Saya tidak menggunakan opsi '-l' meskipun mungkin akan membantu.
Daftar file yang saya tuju mungkin memiliki '-', tetapi bukan baris baru. Saya belum menggunakan file output dengan perintah lain karena saya ingin meninjau apa yang ditemukan sebelum saya baru saja mulai menghapusnya secara besar-besaran melalui xargs.
sumber
Saya bermain dengan ini sedikit, mulai merenungkan memodifikasi xargs, dan menyadari bahwa untuk jenis use case yang sedang kita bicarakan di sini, implementasi ulang sederhana dengan Python adalah ide yang lebih baik.
Untuk satu hal, memiliki ~ 80 baris kode untuk keseluruhan berarti mudah untuk mengetahui apa yang sedang terjadi, dan jika diperlukan perilaku yang berbeda, Anda dapat meretasnya menjadi skrip baru dalam waktu yang lebih singkat daripada waktu yang dibutuhkan untuk mendapatkan balasan di suatu tempat seperti Stack Overflow.
Lihat https://github.com/johnallsup/jda-misc-scripts/blob/master/yargs dan https://github.com/johnallsup/jda-misc-scripts/blob/master/zargs.py .
Dengan yargs seperti ditulis (dan Python 3 terpasang) Anda dapat mengetik:
untuk melakukan menyalin 203 file sekaligus. (Di sini 203 hanya pengganti, tentu saja, dan menggunakan nomor aneh seperti 203 memperjelas bahwa nomor ini tidak memiliki makna lain.)
Jika Anda benar-benar menginginkan sesuatu yang lebih cepat dan tanpa perlu Python, gunakan zargs dan yargs sebagai prototipe dan tulis ulang dalam C ++ atau C.
sumber
Anda mungkin perlu grep direktori Foobar seperti:
sumber
-i
sudah usang, dan-I
harus digunakan sebagai gantinya.Jika Anda menggunakan Bash, Anda dapat mengonversi stdout ke array baris dengan
mapfile
:Manfaatnya adalah:
Anda dapat menambahkan argumen lain ke nama file. Untuk
cp
, Anda juga bisa:Namun, beberapa perintah tidak memiliki fitur tersebut.
Kerugiannya:
Nah ... siapa yang tahu jika Bash tersedia di OS X?
sumber