Birden çok metin dosyasını Bash'te tek bir dosyada birleştirme


305

Bir dizindeki tüm * .txt dosyasını tek bir büyük metin dosyasında birleştirmenin en hızlı ve en pragmatik yolu nedir?

Şu anda cygwin ile windows kullanıyorum, bu yüzden BASH erişimim var.

Windows kabuk komutu da iyi olurdu ama bir tane olduğundan şüpheliyim.

Yanıtlar:


537

Bu, çıktıyı all.txt dosyasına ekler

cat *.txt >> all.txt

Bu, all.txt dosyasının üzerine yazılır

cat *.txt > all.txt

30
all.txt içine all.txt içine kediler bir sorunla karşılaşabilirsiniz ... Bazen grep ile bu sorunu var, kedi aynı davranış olup olmadığını emin değilim.
rmeador

8
@rmeador evet, bu doğrudur, all.txt zaten varsa bu sorunla karşılaşırsınız. Bu sorun, çıktı dosyasına farklı bir uzantı sağlayarak veya all.txt dosyasını farklı bir klasöre taşıyarak çözülür.
Robert Greiner

2
kat * .txt >> tmp; mv tmp all.txt (ve all.txt'nin önceden mevcut olmadığından emin olun)
Renaud

16
"Bağımsız değişken listesi çok uzun" alıyorum - sanırım 40.000'den fazla dosyayı işleyemiyor.
Matt

32
echo *.txt | xargs cat > all.txt
Bağımsız

145

Şimdiye kadar verilen tüm çözümler için kabuğun dosyaların birleştirilme sırasına karar verdiğini unutmayın. Bash için, IIRC, bu alfabetik sıraya göre. Sipariş önemliyse, dosyaları uygun şekilde adlandırmanız (01file.txt, 02file.txt, vb ...) veya her dosyayı birleştirilmesini istediğiniz sırayla belirtmeniz gerekir.

$ cat file1 file2 file3 file4 file5 file6 > out.txt

33

Windows kabuk komutu typeşunları yapabilir:

type *.txt >outputfile

Type typekomutu ayrıca, >yönlendirme operatörü tarafından yakalanmayan (ancak konsolda görünecek) stderr'a dosya adları yazar .


2
Çıktı dosyasını orijinal dosyayla aynı dizine koyarsanız, çoğaltma işlemine neden olacağından, yeni çıktı dosyasını iki kez birleştireceğini unutmayın.
CathalMF

26

copyDosyaları birleştirmek için Windows kabuğunu kullanabilirsiniz .

C:\> copy *.txt outputfile

Yardımdan:

Dosya eklemek için, hedef için tek bir dosya, ancak kaynak için birden fazla dosya belirtin (joker karakterler veya dosya1 + dosya2 + dosya3 biçimini kullanarak).


Bu, yeni başlayanların maalesef yol açabileceği hiçbir yan etkisi olmayan IMHO temiz çözüm olarak ne yazık ki yeterince takdir
edilmiyor

OP Bash istedi.
Büyük Zengin

2
Soruyu okudun mu? "Windows kabuk komutu da iyi olurdu ..."
Carl Norum

8

Dikkatli olun, çünkü bu yöntemlerin hiçbiri çok sayıda dosyayla çalışmaz. Şahsen, bu hattı kullandım:

for i in $(ls | grep ".txt");do cat $i >> output.txt;done

DÜZENLEME: Birisi yorumlar dedi gibi, yerine $(ls | grep ".txt")ile$(ls *.txt)

EDIT: @gnourf_gnourf uzmanlığı sayesinde glob kullanımı bir dizindeki dosyaları yinelemek için doğru yoldur. Sonuç olarak, küfür ifadeleri sever $(ls | grep ".txt")tarafından değiştirilmelidir *.txt(makalesine bakın burada ).

Güzel çözüm

for i in *.txt;do cat $i >> output.txt;done

1
Neden olmasın for i in $(ls *.txt);do cat $i >> output.txt;done?
streamofstars

2
Zorunlu AyrıştırmaLs bağlantısı, bir downvote ile birlikte (ve birden fazla downvote hak ediyorsunuz, çünkü ls | grepciddi derecede kötü bir antipattern ).
gniourf_gniourf

Çıktıdan önce dosya adına göre keyfi testlere / işlemlere izin verdiği ve pratik için hızlı ve kolay ve iyi olduğu için benden bir oy aldım. (Benim durumumda istedim: i için *; yankı -e "\ n $ i: \ n"; kedi $ 1; bitti)
Nathan Chappell

Olmaz ls *.txtçok fazla dosya (Argüman listesi çok uzun hatası) varsa başarısız?
Rafael Almeida

6

kabuk ile en pragmatik yol kedi emridir. diğer yollar arasında,

awk '1' *.txt > all.txt
perl -ne 'print;' *.txt > all.txt

1
Bu çoğu durum için doğru cevap olmalıdır. Boş yeni satır içermeyen herhangi bir metin dosyası varsa, yukarıdaki catyöntemin tümü kullanılarak bitişik dosyalardan son satır ve ilk satır birleştirilir.
mootmoot

6

Bu yaklaşıma ne dersiniz?

find . -type f -name '*.txt' -exec cat {} + >> output.txt

OP, dosyaların aynı dizinde olduğunu -maxdepth 1belirttiğinden, findkomuta eklemeniz gerekebilir .
codeforester

1
Kabul edilen yanıtın yaklaşımının başarısız olduğu çok sayıda dosyayla harika çalışır
amine

ah keşke bu artı ve çift yönlendirme anlam ifade ne biliyordum ...
hello_earth

Bu doğru cevap olmalı. Bir kabuk betiğinde düzgün çalışır. Çıktı sıralı istiyorsanız benzer bir yöntem:sort -u --output="$OUTPUT_FILE" --files0-from=- < <(find "$DIRECTORY_NAME" -maxdepth 1 -type f -name '*.txt' -print0)
steveH

3
type [source folder]\*.[File extension] > [destination folder]\[file name].[File extension]

Örneğin:

type C:\*.txt > C:\1\all.txt

Bu, C: \ Klasöründeki tüm txt dosyalarını alır ve all.txt adına göre C: \ 1 Klasörüne kaydeder

Veya

type [source folder]\* > [destination folder]\[file name].[File extension]

Örneğin:

type C:\* > C:\1\all.txt

Bu, klasörde bulunan tüm dosyaları alır ve C: \ 1 \ all.txt dosyasına İçerik koyar


0

Bunu şöyle yapabilirsiniz: cat [directory_path]/**/*.[h,m] > test.txt

{}bulmak istediğiniz dosyaların uzantısını eklemek için kullanırsanız , bir sıralama sorunu vardır.


0

All.txt dosyasının all.txt içine girdiği bir sorunla karşılaştığınızda, all.txt dosyasının var olup olmadığını kontrol etmeyi deneyebilirsiniz, varsa kaldırın

Bunun gibi:

[ -e $"all.txt" ] && rm $"all.txt"


cat *.txt > all.txt >komutu >>mevcut dosyaya veri eklerse all.txt'nin üzerine yazar
Oleg Bondarenko

-4

tüm bunlar kötü ....

ls | grep *.txt | while read file; do cat $file >> ./output.txt; done;

kolay şeyler.


6
Eeek! Bunu yapma. Dofind . -iname "*.txt" -maxdepth 1 -exec cat {} >> out.txt \;
Chinmay Kanchi
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.