Saya memiliki direktori yang memiliki 10144911 file di dalamnya. Sejauh ini saya sudah mencoba yang berikut ini:
for f in ls; do sed -i -e 's/blah/blee/g' $f; done
Hancur cangkang saya, ls
ada di tilda tetapi saya tidak tahu cara membuatnya.
ls | xargs -0 sed -i -e 's/blah/blee/g'
Terlalu banyak argumen untuk sed
find . -name "*.txt" -exec sed -i -e 's/blah/blee/g' {} \;
Tidak dapat melakukan percabangan lagi, tidak ada lagi memori
Ada ide lain tentang cara membuat perintah semacam ini? File tidak perlu berkomunikasi satu sama lain. ls | wc -l
tampaknya berfungsi (sangat lambat) sehingga harus dimungkinkan.
sed
untuk setiap file. Saya tidak yakin apakah ada cara untuk membuka, mengedit, menyimpan, dan menutup serangkaian file dised
; jika kecepatan sangat penting Anda mungkin ingin menggunakan program yang berbeda, mungkin perl atau python.sed
mungkin lebih cepat daripada meluncurkanpython
atauperl
juga, kecuali jika Anda melakukan segalanya dalam penerjemah itu.Jawaban:
Cobalah ini:
Itu hanya akan memberi makan satu nama file untuk setiap doa
sed
. Itu akan memecahkan masalah "terlalu banyak args untuk sed". The-P
pilihan harus memungkinkan beberapa proses yang harus bercabang pada waktu yang sama. Jika 0 tidak berfungsi (seharusnya menjalankan sebanyak mungkin), coba angka lainnya (10? 100? Jumlah inti yang Anda miliki?) Untuk membatasi jumlahnya.sumber
find . -name \*.txt -print0
menghindari shell memperluas glob dan mencoba untuk mengalokasikan ruang untuk 10 juta argumen untuk ditemukan .Saya telah menguji metode ini (dan yang lainnya) pada 10 juta file (kosong), bernama "halo 00000001" menjadi "halo 10000000" (14 byte per nama).
UPDATE: Saya sekarang sudah memasukkan menjalankan quad-core pada
'find |xargs'
metode (masih tanpa 'sed'; just echo> / dev / null) ..Berikut ringkasan bagaimana jawaban yang diberikan bernasib ketika dijalankan terhadap data uji yang disebutkan di atas. Hasil ini hanya melibatkan biaya dasar; yaitu 'sed' tidak dipanggil. Proses sed hampir pasti akan menjadi yang paling memakan waktu, tetapi saya pikir akan menarik untuk melihat bagaimana metode telanjang dibandingkan.
'find |xargs'
Metode Dennis , menggunakan single core, membutuhkan waktu * 4 jam 21 menit ** lebih lama daripadabash array
metode yangno sed
dijalankan ... Namun, keunggulan multi-core yang ditawarkan oleh 'find' harus lebih besar daripada perbedaan waktu yang ditunjukkan ketika sed dipanggil untuk memproses file ...sumber
Peluang lain untuk penemuan yang sepenuhnya aman :
sumber
Ini sebagian besar di luar topik, tetapi Anda dapat menggunakannya
Manfaat utama di sini (lebih
... xargs ... -I {} ... sed ...
) adalah kecepatan: Anda menghindari memintased
10 juta kali. Akan lebih cepat lagi jika Anda bisa menghindari menggunakan Python (karena python agak lambat, relatif), jadi perl mungkin merupakan pilihan yang lebih baik untuk tugas ini. Saya tidak yakin bagaimana melakukan yang setara dengan nyaman dengan perl.Cara ini bekerja adalah yang
xargs
akan memanggil Python dengan argumen sebanyak yang dapat ditampung pada satu baris perintah, dan terus melakukan itu sampai kehabisan argumen (yang dipasok olehls -f *.txt
). Jumlah argumen untuk setiap doa akan tergantung pada panjang nama file dan, um, beberapa hal lainnya. Itufileinput.input
Fungsi menghasilkan garis berurutan dari file bernama dalam argumen setiap permintaan ini, daninplace
pilihan mengatakan itu untuk ajaib "menangkap" output dan menggunakannya untuk mengganti setiap baris.Perhatikan bahwa
replace
metode string Python tidak menggunakan regexps; jika Anda membutuhkannya, Anda harusimport re
dan menggunakannyaprint re.sub(line, "blah", "blee")
. Mereka adalah Perl-Compatible RegExps, yang merupakan semacam versi yang sangat dijaga dari yang Anda dapatkansed -r
.sunting
Seperti akira menyebutkan dalam komentar, versi asli menggunakan glob (
ls -f *.txt
) sebagai gantifind
perintah tidak akan berfungsi karena gumpalan diproses oleh shell (bash
) itu sendiri. Ini berarti bahwa bahkan sebelum perintah dijalankan, 10 juta nama file akan diganti ke dalam baris perintah. Ini cukup dijamin untuk melebihi ukuran maksimum dari daftar argumen perintah. Kamu bisa memakaixargs --show-limits
info khusus sistem untuk ini.Ukuran maksimum dari daftar argumen juga diperhitungkan oleh
xargs
, yang membatasi jumlah argumen yang diteruskan ke setiap pemanggilan python sesuai dengan batas itu. Karenaxargs
masih harus memanggil python beberapa kali, saran akira untuk menggunakanos.path.walk
untuk mendapatkan daftar file mungkin akan menghemat waktu Anda.sumber
os.path.walk()
?.
dan..
. Tentu saja ada cara lain untuk melakukan itu (yaitufind
) tetapi saya mencoba untuk tetap sedekat mungkin dengan apa yang dipahami OP. Ini juga alasan untuk tidak menggunakanos.path.walk
.os.path.walk
dengan mudah.Mencoba:
sumber
ls -f
akan lebih baik; apakah Anda benar-benar ingin menunggustat()
dan mengurutkan banyak file?