Birden çok dosyayı birleştirin ancak dosya adını bölüm üstbilgileri olarak ekleyin


354

Terminaldeki büyük bir dosyaya bir dizi metin dosyasını birleştirmek istiyorum. Bunu cat komutunu kullanarak yapabileceğimi biliyorum. Ancak, her dosyanın dosya adı "veri dökümü" o dosya için önce istiyorum. Bunu nasıl yapacağını bilen var mı?

şu anda ne var:

file1.txt = bluemoongoodbeer

file2.txt = awesomepossum

file3.txt = hownowbrowncow

cat file1.txt file2.txt file3.txt

Istenilen çıktı:

file1

bluemoongoodbeer

file2

awesomepossum

file3

hownowbrowncow

aslında uuencode & uudecode benzer bir şey yapmak için kullanıyorum, ben dosya okunabilir inbetween gerek yok, sadece sonuca ihtiyacım ve tekrar başka bir komut onları boru

Yanıtlar:


532

Aynı şeyi arıyordum ve bunu önermek için buldum:

tail -n +1 file1.txt file2.txt file3.txt

Çıktı:

==> file1.txt <==
<contents of file1.txt>

==> file2.txt <==
<contents of file2.txt>

==> file3.txt <==
<contents of file3.txt>

Yalnızca tek bir dosya varsa, başlık yazdırılmaz. GNU araçları kullanıyorsanız -v, her zaman bir başlık yazdırmak için kullanabilirsiniz .


2
Bu, GNU kuyruğu (GNU Coreutils'in bir parçası) ile de çalışır.
ArjunShankar

8
Harika bir -n +1seçenek! Alternatif: head -n-0 file1 file2 file3.
Donmuş Alev

3
MacOS X'te hem BSD kuyruğu hem de GNU kuyruğu ile harika çalışır . -nVe arasındaki boşlukları +1olduğu gibi bırakabilirsiniz -n+1.
vdm

4
tail -n +1 *tam olarak ben arıyordum, teşekkürler!
kR105

1
MacOsX 10.14.4sudo ulimit -n 1024; find -f . -name "*.rb" | xargs tail -n+1 > ./source_ruby.txt
kolas

187

Benzer bir şey için grep kullandım:

grep "" *.txt

Size bir 'üstbilgi' vermez, ancak her satıra dosya adı ekler.


10
*.txtYalnızca bir dosyaya genişletilirse çıktı kesilir . Bu bağlamda, tavsiye ederimgrep '' /dev/null *.txt
antak

1
Bana grep için yeni bir kullanım göstermek için +1. bu benim ihtiyaçlarımı mükemmel karşıladı. Benim durumumda, her dosya sadece bir satır içeriyordu, bu yüzden bana kolayca
ayrıştırılabilen

9
grepdosya başlıklarını yalnızca birden fazla dosya varsa yazdırır. Her zaman dosya yolunu yazdırdığınızdan emin olmak için kullanın -H. Üstbilgilerin kullanılmasını istemiyorsanız -h. Ayrıca (standard input)STDIN için yazdıracağını unutmayın .
Jorge Bucaran

1
Ayrıca ag(gümüş arama): kullanabilirsiniz, varsayılan olarak, ag . *.txther dosyanın adını ve her satırın numarasını önek olarak kullanır.
anol

1
Dikkat çekici bir şekilde, -ngrep'e geçmek, örneğin emaclar tarafından toplanabilecek saptama ile basit tiftikler yazmanıza izin veren satır numaraları da verir.
DepressedDaniel

105

Bu da hile yapmalı:

find . -type f -print -exec cat {} \;

Anlamına geliyor:

find    = linux `find` command finds filenames, see `man find` for more info
.       = in current directory
-type f = only files, not directories
-print  = show found file
-exec   = additionally execute another linux command
cat     = linux `cat` command, see `man cat`, displays file contents
{}      = placeholder for the currently found filename
\;      = tell `find` command that it ends now here

Ayrıca, -andveya gibi boole operatörleriyle aramaları birleştirebilirsiniz -or. find -lsgüzel de.


1
Bu komutun ne yaptığını daha fazla açıklayabilir misiniz? Tam olarak ihtiyacım olan şey
AAlvz

5
Bu linux'un standart bulma komutudur. Geçerli dizindeki tüm dosyaları arar, adlarını yazdırır, ardından her biri için dosyayı kediler. -printDosya adının önüne basılmayacaksa cat.
Maxim_united

18
-printfÇıktıyı özelleştirmek için de kullanabilirsiniz . Örneğin:find *.conf -type f -printf '\n==> %p <==\n' -exec cat {} \;tail -n +1 *
Maxim_united

1
Eğer istemedikçe -printf, mac üzerinde çalışmaya değil brew install findutilsve daha sonra kullanmak gfindyerine find.
Matt Fletcher

2
Renk istiyorsanız, findbirden fazla -execs sağlayan bu gerçeği kullanabilirsiniz :find -name '*.conf' -exec printf '\n\e[33;1m%s\e[0m\n' {} \; -exec cat {} \;
banbh

24

Bu hile yapmalı:

for filename in file1.txt file2.txt file3.txt; do
    echo "$filename"
    cat "$filename"
done > output.txt

veya bunu tüm metin dosyaları için yinelemeli olarak yapmak için:

find . -type f -name '*.txt' -print | while read filename; do
    echo "$filename"
    cat "$filename"
done > output.txt

1
işe yaramadı. Sadece bazı çirkin awk kod yazdım: $ listoffiles için i awk yapmak '{print FILENAME, 0 $, 1 $, 2 $, 3 $, 4 $, 5 $, 6 $, 7 $, 8 $, 9 $, 10 $, 11 $}' $ i >> concat.txt yapıldı
Nick

2
... özen göstermeye özen gösteriyor musunuz? Bu bash kodu almak kadar basit.
Chris Eberle

@Nick: Awk hattın $0, tüm çizgi olduğunu düşünerek bile çalışmamalı, bu yüzden orada tekrarlayan sütunlar var ...
Chris Eberle

@Nick: Aksi takdirde Şık çözüm :)
Chris Eberle

@Chris: evet, ama olmasını istediğimden çok daha çirkin. Belki kodunu benim için çalışmıyor çünkü stdout yakalamak için >> kullanıyorum?
Nick

17

Dosya adları ile birleştirmek istediğim stats.txt ile biten bir dizi dosyam vardı.

Aşağıdakileri yaptım ve birden fazla dosya olduğunda "more" komutu dosya adını başlık olarak içerir.

more *stats.txt > stats.txt

veya genel bir dava için

more FILES_TO_CONCAT > OUTPUT_FILE

6
more <FILES> | cat
Acumenus

15
find . -type f -print0 | xargs -0 -I % sh -c 'echo %; cat %'

Böylece tam dosya adı (yol dahil) ve ardından dosyanın içeriği yazdırılır. Ayrıca, find komutu için -name "expr" kullanabileceğiniz ve dosyalarda istediğiniz kadar komut çalıştırabileceğiniz için çok esnektir.


1
Ayrıca, birleştirmek oldukça kolaydır grep. bashfind . -type f -print | grep PATTERN | xargs -n 1 -I {} -i bash -c 'echo ==== {} ====; cat {}; echo'
İle

5

Ben normalde böyle biçimlendirme nasıl işlenir:

for i in *; do echo "$i"; echo ; cat "$i"; echo ; done ;

Genellikle belirli bilgiler için kediyi bir grep içine sokarım.


3
Burada dikkatli ol. for i in *alt dizinleri içermez.
Acumenus

5

Bu seçeneği beğendim

for x in $(ls ./*.php); do echo $x; cat $x | grep -i 'menuItem'; done

Çıktı şöyle görünür:

./debug-things.php
./Facebook.Pixel.Code.php
./footer.trusted.seller.items.php
./GoogleAnalytics.php
./JivositeCode.php
./Live-Messenger.php
./mPopex.php
./NOTIFICATIONS-box.php
./reviewPopUp_Frame.php
            $('#top-nav-scroller-pos-<?=$active**MenuItem**;?>').addClass('active');
            gotTo**MenuItem**();
./Reviews-Frames-PopUps.php
./social.media.login.btns.php
./social-side-bar.php
./staticWalletsAlerst.php
./tmp-fix.php
./top-nav-scroller.php
$active**MenuItem** = '0';
        $active**MenuItem** = '1';
        $active**MenuItem** = '2';
        $active**MenuItem** = '3';
./Waiting-Overlay.php
./Yandex.Metrika.php


3

for döngüsü kullanmak yerine bu basit komutu kullanabilirsiniz,

ls -ltr | awk '{print $9}' | xargs head

3

Renklerden hoşlanıyorsanız, şunu deneyin:

for i in *; do echo; echo $'\e[33;1m'$i$'\e[0m'; cat $i; done | less -R

veya:

tail -n +1 * | grep -e $ -e '==.*'

veya: ('multitail' paketiyle)

multitail *

1
Dosya find . -type f -name "*.txt" | xargs -I {} bash -c "echo $'\e[33;1m'{}$'\e[0m';cat {}"
adını

3

Dosyaların tümü aynı ada sahipse veya ile eşleştirilebiliyorsa findşunları yapabilirsiniz (örn.):

find . -name create.sh | xargs tail -n +1

bulmak, yol göstermek ve her dosyanın cat.


2

İşte gerçekten basit bir yol. Tüm dosyayı görüntülemek istediğinizi ima etmek için kedi istediğinizi söylediniz. Ancak yazdırılmış dosya adına da ihtiyacınız var.

Bunu dene

head -n99999999 * veya head -n99999999 file1.txt file2.txt file3.txt

umarım yardımcı olur


4
daha temiz bir sözdizimi olurdu head -n -0 file.txt file2.txt file3.txt. İçin çalışır headGNU coreutils içerisinde
DoubleDown

1

Bu yöntem dosya adını ve ardından dosya içeriğini yazdırır:

tail -f file1.txt file2.txt

Çıktı:

==> file1.txt <==
contents of file1.txt ...
contents of file1.txt ...

==> file2.txt <==
contents of file2.txt ...
contents of file2.txt ...

3
Bu -f, OP'nin istediği kapsamda değil, yazılan bir dosyayı izlemek istiyorsanız yararlıdır.
üçlü

1

Bu çirkin ==> <== yerine başka bir şey koymak istiyorsanız

tail -n +1 *.txt | sed -e 's/==>/\n###/g' -e 's/<==/###/g' >> "files.txt"

açıklama:

tail -n +1 *.txt - klasördeki tüm dosyaları üstbilgiyle çıktılar

sed -e 's/==>/\n###/g' -e 's/<==/###/g'- değiştirin ==>ile yeni hat + ### ve <==sadece birlikte ###

>> "files.txt" - tümünü bir dosyaya çıktılar



0

Sonucu istediğiniz çıktıyla aynı biçimde istiyorsanız deneyebilirsiniz:

for file in `ls file{1..3}.txt`; \
do echo $file | cut -d '.' -f 1; \ 
cat $file  ; done;

Sonuç:

file1
bluemoongoodbeer
file2
awesomepossum
file3
hownowbrowncow

Kesimlerden echo -eönce ve sonra koyabilirsiniz , böylece çizgiler arasındaki boşluğa da sahip olursunuz:

$ for file in `ls file{1..3}.txt`; do echo $file | cut -d '.' -f 1; echo -e; cat $file; echo -e  ; done;

Sonuç:

file1

bluemoongoodbeer

file2

awesomepossum

file3

hownowbrowncow

Explanation: forloop, lskomutun verdiği listeye gider . $ ls file{1..3}.txtSonuç: file1.txt file2.txt file3.txtHer yineleme olacak dize o zaman içine taşınıyor oluyor kullandığım komuta alan1 dışında iki adet ve baskılar (field2 txt olan) geri kalan açık olmalıdır içine fileX.txt kırar alan ayracı olarakecho$filecut.
Fekete Sümer

0
  • AIX 7.1 ksh

... bazılarımız için kafa işlerinden daha önce bahsetmiş olanlara hitap etmek :

$ r head
head file*.txt
==> file1.txt <==
xxx
111

==> file2.txt <==
yyy
222
nyuk nyuk nyuk

==> file3.txt <==
zzz
$

İhtiyacım ilk satırı okumak; belirtildiği gibi, 10'dan fazla satır istiyorsanız, seçenekler eklemeniz gerekir (kafa -9999, vb.).

Türev bir yorum gönderdiğim için üzgünüm; Yorum yapmak / birisinin yorumuna eklemek için yeterli sokak kredim yok.


-1

Bu görevleri çözmek için genellikle aşağıdaki komutu kullanıyorum:

$ cat file{1..3}.txt >> result.txt

Dosya sayısı oldukça büyükse, dosyaları birleştirmenin çok kolay bir yoludur.


1
Ancak bu OP'nin sorusuna cevap vermiyor.
kvantour

-3

Önce her dosyayı oluşturdum: echo 'information'> file1.txt her dosya için [123] .txt.

Sonra bilgilerin doğru olduğundan emin olmak için her dosyayı yazdırdım: kuyruk dosyası? .Txt

Sonra bunu yaptım: kuyruk dosyası? .Txt >> Mainfile.txt. Bu, her dosyadaki bilgileri bir ana dosyaya depolamak için Mainfile.txt dosyasını oluşturdu.

cat Mainfile.txt iyi olduğunu onayladı.

==> file1.txt <== bluemoongoodbeer

==> file2.txt <== awesomepossum

==> file3.txt <== hownowbrowncow

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.