Saya memiliki ± 10.000 file ( res.1
- res.10000
) yang semuanya terdiri dari satu kolom, dan jumlah baris yang sama. Yang saya inginkan adalah, pada dasarnya, sederhana; gabungkan semua file dengan bijaksana dalam file baru final.res
. Saya sudah mencoba menggunakan:
paste res.*
Namun (meskipun hal ini tampaknya bekerja untuk subset kecil dari file hasil, ini memberikan error berikut ketika dilakukan pada seluruh set: Too many open files
.
Pasti ada cara 'mudah' untuk menyelesaikan ini, tapi sayangnya saya cukup baru untuk unix. Terima kasih sebelumnya!
PS: Untuk memberi Anda gambaran tentang bagaimana (salah satu) datafile terlihat seperti:
0.5
0.5
0.03825
0.5
10211.0457
10227.8469
-5102.5228
0.0742
3.0944
...
--serial
opsi denganpaste
perintah?paste --serial
tidak menggabungkan file dengan bijaksana ...paste -s
memang berfungsi, tetapi menempelkan hasil yang terpisah file bijaksana baris bukan kolom bijaksana. Namun, ini adalah sesuatu yang bisa saya pecahkan. Terima kasih!Jawaban:
Jika Anda memiliki izin root pada mesin itu, Anda sementara dapat meningkatkan batas "jumlah maksimum deskriptor file terbuka":
Lalu
Setelah itu Anda dapat mengaturnya kembali ke nilai aslinya.
Sebuah solusi kedua , jika Anda tidak dapat mengubah batas:
Ini panggilan
paste
untuk setiap file satu kali, dan pada akhirnya ada file besar dengan semua kolom (perlu beberapa menit).Sunting : Penggunaan kucing yang tidak berguna ... Tidak !
Seperti disebutkan dalam komentar penggunaan di
cat
sini (cat final.res | paste - $f >temp
) tidak sia-sia. Pertama kali loop dijalankan, filefinal.res
belum ada.paste
kemudian akan gagal dan file tidak pernah diisi, atau dibuat. Dengan solusi saya hanyacat
gagal pertama kali denganNo such file or directory
danpaste
membaca dari stdin hanya file kosong, tetapi terus berlanjut. Kesalahan bisa diabaikan.sumber
ulimit -Sn
untuk batas lunak danulimit -Hn
batas keras-bash: /usr/bin/paste: Argument list too long
. Gagasan bagaimana mengatasi ini? Maaf mengganggu kalian.getconf ARG_MAX
, Anda hanya dapat meningkatkan nilai itu saat mengkompilasi ulang kernel. Anda dapat mencoba solusi kedua saya?cat
setiap kali melalui loop, Anda bisa mulai dengan membuatfinal.res
file kosong . Ini mungkin ide yang bagus, kalau-kalau sudah adafinal.res
file di sana.Jika jawaban chaos tidak berlaku (karena Anda tidak memiliki izin yang diperlukan), Anda dapat mengumpulkan
paste
panggilan sebagai berikut:Ini mencantumkan file 1000 sekaligus dalam file bernama
lists00
,lists01
dll., Lalu menempelkanres.
file yang sesuai ke file bernamamerge00
,merge01
dll., Dan akhirnya menggabungkan semua file yang digabungkan sebagian.Seperti disebutkan oleh kekacauan Anda dapat meningkatkan jumlah file yang digunakan sekaligus; batasnya adalah nilai yang diberikan
ulimit -n
dikurangi berapa banyak file yang sudah Anda buka, jadi Anda akan mengatakannyauntuk menggunakan batas minus sepuluh.
Jika versi
split
Anda tidak mendukung-d
, Anda dapat menghapusnya: yang diperlukan hanyalahsplit
sufiks numerik. Secara default sufiksnya adalahaa
,ab
dll. , Bukan01
,02
dll.Jika ada begitu banyak file yang
ls -1 res.*
gagal ("daftar argumen terlalu panjang"), Anda dapat menggantinya denganfind
yang akan menghindari kesalahan itu:(Seperti yang ditunjukkan oleh don_crissti ,
-1
seharusnya tidak perlu ketikals
mengeluarkan piping ; tapi saya meninggalkannya untuk menangani kasus-kasus di manals
alias dengan-C
.)sumber
Coba jalankan dengan cara ini:
Anda juga dapat membagi batch menjadi beberapa bagian dan mencoba sesuatu seperti:
dan pada akhirnya menggabungkan file akhir
sumber
Too many open files
final.x00
be be pipe - baik sebagai yang bernama FIFOs, atau secara implisit, menggunakan substitusi proses (jika shell Anda mendukungnya - misalnya bash). Ini tidak menyenangkan untuk ditulis dengan tangan, tetapi mungkin cocok untuk makefile.Saya tidak berpikir ini serumit semua itu - Anda sudah melakukan kerja keras dengan memesan nama file. Hanya saja, jangan membuka semuanya sekaligus, itu saja.
Cara lain:
... tapi saya pikir itu membuat mereka mundur ... Ini mungkin bekerja lebih baik:
Dan inilah cara lain :
Yang memungkinkan
tar
untuk mengumpulkan semua file menjadi aliran tanpa batas nol untuk Anda, mem-parsing semua metadata headernya kecuali nama file, dan mengubah semua baris di semua file menjadi tab. Itu bergantung pada input menjadi file teks aktual - yang berarti masing-masing berakhir dengan baris baru dan tidak ada null-byte dalam file. Oh - dan juga bergantung pada nama file sendiri menjadi baris baru bebas (meskipun yang mungkin ditangani bersemangat dengan GNUtar
's--xform
pilihan) . Mengingat kondisi ini terpenuhi, itu harus membuat pekerjaan yang sangat singkat dari sejumlah file - dantar
akan melakukan hampir semua itu.Hasilnya adalah serangkaian garis yang terlihat seperti:
Dan seterusnya.
Saya mengujinya dengan terlebih dahulu membuat 5 testfile. Saya tidak benar-benar ingin membuat 10.000 file sekarang, jadi saya hanya sedikit lebih besar untuk masing-masing - dan juga memastikan bahwa panjang file berbeda dengan banyak. Ini penting ketika menguji
tar
skrip karenatar
akan memblokir input ke panjang tetap - jika Anda tidak mencoba setidaknya beberapa panjang berbeda Anda tidak akan pernah tahu apakah Anda benar-benar akan menangani hanya satu.Lagi pula, untuk file tes yang saya lakukan:
ls
setelah itu dilaporkan:... lalu aku berlari ...
... hanya untuk menampilkan hanya 25 bidang tab-dibatasi pertama per baris (karena setiap file adalah satu baris - ada banyak ) ...
Outputnya adalah:
sumber
Mengingat jumlah file, ukuran garis, dll. Yang terlibat, saya pikir itu akan melampaui ukuran standar alat (awk, sed, paste, *, dll)
Saya akan membuat program kecil untuk ini, tidak akan ada 10.000 file yang terbuka, atau panjang baris ratusan ribu (10.000 file 10 (ukuran maksimum baris dalam contoh)). Hanya membutuhkan ~ 10.000 array bilangan bulat, untuk menyimpan jumlah byte yang telah dibaca dari setiap file. Kerugiannya adalah ia hanya memiliki satu deskriptor file, digunakan kembali untuk setiap file, untuk setiap baris, dan ini bisa lambat.
Definisi
FILES
danROWS
harus diubah ke nilai sebenarnya yang sebenarnya. Output dikirim ke output standar.sumber