Dosyaları birleştirmenin en hızlı yolu


25

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.


Cevabım güncellendi, finddosyaları kabuk kabuğu ile aynı şekilde sıralamıyor.
Graeme

5
Herhangi bir ve tüm (akıllı) çözümler burada% 99 sistem G / Ç olacağı için burada eşdeğer bir hızda olacaktır.
goldilock,


3
Birleştirilmiş dosyayı, okuduğunuzdan farklı bir diske yazmayı düşünün.
Luis

1
outBaşka bir diskte bulunursa daha hızlı olacaktır .

Yanıtlar:


30

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

1
Bu durumda dosyalarınızın sırayla okunacağından emin olabilir misiniz?
Kiwy

1
Evet, çünkü çıkışı findiletildi sort. Bu olmadan, dosyalar rastgele bir sırayla listelenir (dosya sistemi tarafından tanımlanabilen, dosya oluşturma sırası olabilir).
scai

@scai Üzgünüm özledim, sıralama oldukça açık
Kiwy

1
@Kiwy, görebildiğim tek durum, yerel ayarların çevrede düzgün bir şekilde ayarlanmamış olması durumunda, sıralama bir bashküreden farklı davranabilir . Aksi takdirde beklendiği gibi davranan xargsveya catdavranmayan hiçbir durum göremiyorum .
Graeme

3
@MarcvanLeeuwen, xargsmay olarak arayacak catşekilde execve (2) bir E2BIG hatayı önlemek için gereklidir.
Stéphane Chazelas

21

Ö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

1
@XTian, hayır, olması ne olmalı >, ne de >>, ama 1<>dediğim gibi yazmaya içine dosyanın.
Stéphane Chazelas

5
@grebneke, <>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).
Stéphane Chazelas

1
@grebneke, unix.stackexchange.com/search?q=user%3A22565+%22%3C%3E%22 size birkaç tane verir. ksh93 BTW operatörlerini aramaktadır ve ddokuyarak veya okuyarak ileriye bakabilirsiniz .
Stéphane Chazelas

1
@StephaneChazelas - çok teşekkürler, yardımlarınız ve bilginiz derinden takdir edilir!
grebneke

1
İkinci seferde daha hızlı olmasına rağmen 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.
Graeme
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.