Tek bir dosyada birleştirmem gereken 20 GB'ın üzerinde toplam 10k + dosyam var.
Daha hızlı bir yolu var mı
cat input_file* >> out
?
Tercih edilen yol bir bash komutu olacaktır, Python da oldukça yavaş olmasa da kabul edilebilir.
Tek bir dosyada birleştirmem gereken 20 GB'ın üzerinde toplam 10k + dosyam var.
Daha hızlı bir yolu var mı
cat input_file* >> out
?
Tercih edilen yol bir bash komutu olacaktır, Python da oldukça yavaş olmasa da kabul edilebilir.
Yanıtlar:
Hayır, kedi kesinlikle bunu yapmanın en iyi yoludur. Bu amaçla C dilinde yazılmış bir program varken neden python kullanmalıyım? Bununla birlikte, xargs
komut satırı uzunluğunun aşılması ARG_MAX
ve birden fazla kişiye ihtiyacınız olması durumunda kullanmayı düşünebilirsiniz cat
. GNU araçlarını kullanmak, sahip olduğunuza eşdeğerdir:
find . -maxdepth 1 -type f -name 'input_file*' -print0 |
sort -z |
xargs -0 cat -- >>out
find
iletildi sort
. Bu olmadan, dosyalar rastgele bir sırayla listelenir (dosya sistemi tarafından tanımlanabilen, dosya oluşturma sırası olabilir).
bash
küreden farklı davranabilir . Aksi takdirde beklendiği gibi davranan xargs
veya cat
davranmayan hiçbir durum göremiyorum .
xargs
may olarak arayacak cat
şekilde execve (2) bir E2BIG hatayı önlemek için gereklidir.
Öncelikle çıktı dosyası için alan tahsis etmek, sistemin her yazma için tahsisi güncellemesi gerekmeyeceğinden genel hızı artırabilir.
Örneğin, eğer Linux'ta:
size=$({ find . -maxdepth 1 -type f -name 'input_file*' -printf '%s+'; echo 0;} | bc)
fallocate -l "$size" out &&
find . -maxdepth 1 -type f -name 'input_file*' -print0 |
sort -z | xargs -r0 cat 1<> out
Diğer bir yararı, eğer yeterli boş alan yoksa, kopya denenmeyecek olmasıdır.
Üzerinde ise btrfs
, yapabilirsin copy --reflink=always
, ve dinlenme ekleyin (hiçbir veri kopyalamak ve bu nedenle neredeyse anında ortaya çıkacaktır ima) ilk dosya. 10000 dosya varsa, ilk dosya çok büyük olmadıkça bu muhtemelen çok fazla farketmez.
Orada tüm dosyaları (ref-kopyalamanız genelleme için bir API var BTRFS_IOC_CLONE_RANGE
ioctl
), ancak C bunu yapmak zorundayız bu yüzden, bu API açığa herhangi yarar bulamadı (ya python
veya diğer dillere keyfi çağırabilir sağlanan ioctl
s) .
Kaynak dosyalar seyrekse veya çok sayıda NUL karakter dizisine sahipse, (GNU sistemlerde) ile seyrek bir çıktı dosyası (zamandan ve disk alanından tasarruf) yapabilirsiniz:
find . -maxdepth 1 -type f -name 'input_file*' -print0 |
sort -z | xargs -r0 cat | cp --sparse=always /dev/stdin out
>
, ne de >>
, ama 1<>
dediğim gibi yazmaya içine dosyanın.
<>
standart Bourne / POSIX okuma + yazma yönlendirme operatörüdür. Ayrıntılar için kabuk kılavuzunuza veya POSIX teknik özelliklerine bakın. Varsayılan fd
olduğu 0
için <>
operatör ( <>
kısaltmasıdır 0<>
gibi <
kısa içindir 0<
ve >
kısaca 1>
ihtiyacınız böylece) 1
açıkça yönlendirme Stdout'a. Burada, biz + yazmayı (okuma gerek o kadar çok değil O_RDWR
), ama biz istemiyoruz O_TRUNC
(olduğu gibi >
biz sadece tahsis kadarıyla ayırması olan).
dd
okuyarak veya okuyarak ileriye bakabilirsiniz .
fallocate
, fazladan ek yükü olumsuz etkileyecek pek çok vaka olacağına ikna olmadım find
. btrfs
kesinlikle olsa da bazı ilginç olasılıklar açılıyor.
find
dosyaları kabuk kabuğu ile aynı şekilde sıralamıyor.