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, xargskomut satırı uzunluğunun aşılması ARG_MAXve 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
findiletildi sort. Bu olmadan, dosyalar rastgele bir sırayla listelenir (dosya sistemi tarafından tanımlanabilen, dosya oluşturma sırası olabilir).
bashküreden farklı davranabilir . Aksi takdirde beklendiği gibi davranan xargsveya catdavranmayan hiçbir durum göremiyorum .
xargsmay 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 pythonveya diğer dillere keyfi çağırabilir sağlanan ioctls) .
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 fdolduğu 0için <>operatör ( <>kısaltmasıdır 0<>gibi <kısa içindir 0<ve >kısaca 1>ihtiyacınız böylece) 1açı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).
ddokuyarak veya okuyarak ileriye bakabilirsiniz .
fallocate, fazladan ek yükü olumsuz etkileyecek pek çok vaka olacağına ikna olmadım find. btrfskesinlikle olsa da bazı ilginç olasılıklar açılıyor.
finddosyaları kabuk kabuğu ile aynı şekilde sıralamıyor.