Dosya içeriğini stdout'a çıkarmak için komut?


28

Bunu catyapabileceğimi biliyorum , ancak asıl amacı yalnızca içeriği görüntülemek yerine birleştirmektir.

Ayrıca biliyorum lessve more, ancak sadece bir dosyanın içeriğini terminale çıkaran basit bir şey arıyorum ( çağrı cihazı değil ) ve böyle bir şey varsa, bunun için özel olarak yapılmış.


1
Aslında cat kullandığınız zamanların% 99'u bir şey birleştirmek yerine dosyaları görüntülemek içindir.
LatinSuD

1
@LatinSuD - zamanın% 100'ü - catbirleştirir.
mikeserv

@mikeserv: Bir operasyon gerçekleştirerek ne demek istediğinizi meselesidir; normal dil kullanımı en az bir kere yapıldığını ima etmek olacaktır. Boş bir dize "yazdırma" herhangi bir karakter yazdırmayı içermez; hiçbir şey basmadığını söylemek doğru olmaz. Şimdi hesaplama a+b+c2 ekleme yapmayı içerir ve hesaplama ahiçbir şey eklemeyi içermez. Benzer şekilde yürütmek cat fhiçbir şeyi birleştirmeyi içermez ("tek bir dosya dizisini birleştiren tek şey bu olsa bile" anlamına gelebilir).
Marc van Leeuwen

2
@mikeserv: Ne demek istediğin içinde in + out anlamıyorum. Sure catbir dosyayı okur ve başka bir dosya (akış) yazar, ancak bu bir şey birleştirdiği anlamına gelmez. Belki de bunun cat fgerçekten yaptığını kastediyorsan cat - f, bu doğru değil.
Marc van Leeuwen

1
@ confused00: catgerçekten birleştirmek gerekiyordu ( cat file1 file2her iki dosyayı da stdout ile birleştiriyor). Ancak bunun yan etkisi, yalnızca argüman olarak 1 dosya bulunduğunda, o dosyayı stdout'a çıkarır (nereye giderse gitsin, terminalin ya da bir şeye yönlendirilir). Dolayısıyla, sadece catvar olduğu ve izin verdiği şekilde sadece stdout'ta çıktı almak için oluşturulan başka bir komut yoktu . Bu nedenle kullanmak istiyorsun cat.
Olivier Dulac

Yanıtlar:


37

En belirgin olanı cat. Ama, aynı zamanda bir göz headve tail. Çizgi ile bir dosya hattını yazdırmak için diğer kabuk utillities da vardır: sed, awk, grep. Ancak bunlar dosya içeriğini değiştirmek veya dosyanın içinde arama yapmaktır.

Hangisinin en etkili olduğunu tahmin etmek için birkaç test yaptım. straceEn az sistem çağrısının hangisinin yapıldığını görmek için tüm yoldan koşarım . Dosyamın 1275 satırı var.

  • awk: 1355 sistem çağrısı
  • cat: 51 sistem çağrısı
  • grep: 1337 sistem çağrısı
  • head: 93 sistem çağrısı
  • tail: 130 sistem çağrısı
  • sed: 1378 sistem çağrısı

Gördüğünüz gibi, catdosyaları birleştirmek için tasarlanmış olsa bile , en hızlı ve en etkili olanıdır. sed, awkVe grep, dosyayı satır satır baskılı onlar daha o 1275 sistem çağrıları neden.


8
Sistem çağrılarını saymak iyi fikir!
Jan

1
+1, cevap daha kesin (kedinin anlamı hakkında), daha eksiksiz (alternatifler) ve araştırılmış (sistemler)
Olivier Dulac

23

Bunu catyapabileceğimi biliyorum , ancak asıl amacı yalnızca içeriği görüntülemek yerine birleştirmektir.

Bunun amacı cattam olarak bir dosyayı okumak ve stdout'a çıkarmaktır.


1
Ancak cat --help"DOSYAL (lar) ı veya standart girişi standart çıktı olarak birleştirin" diyor. Hiçbir şey birleştirmek istemiyorum
kafası karışmış00

18
İster inan ister inanma, kedi tam olarak aradığın şey.
Jan

5
Hayır, @ şaşkın00, Jan haklı. Şey - terminali olan stdout'u - Gördüğünüz? do readlink /dev/fd/1örneğin - Orada TTY adını almalısınız istemi standart çalışan eğer. Yani girdiyi çıktı ile bitiştirmek, sizden ne istediğiniz.
mikeserv

2
@mikeserv Evet, amacınızı anlıyorum, sanırım 'birleştirmek' anlamını çok düzelttim.
confused00

3
Mantık, bir dosyanın içeriğini yazdırmak, sırayla bir veya daha fazla dosyanın içeriğini yazdırmak için özel bir durumdur .
zwol

10

İlk olarak, etkileşimli bir kabuğa komutun bir parçası olarak yazılsa catbile, mutlaka bir terminal olması gerekmeyen standart çıktıya yazar cat. Standart çıktı yönlendirildiğinde bile terminale yazmak için bir şeye ihtiyacınız varsa, bu o kadar kolay değildir (hangi terminali belirtmeniz gerekir, komut komuttan çalıştırılırsa bir tane bile olmayabilir). (ab) komut yalnızca bir boru hattının bir parçasıysa standart hata çıktısını kullanabilir. Ama catişi gerçekten yaptığını söylediğinden beri , böyle bir durum hakkında soru sormadığını düşünüyorum.

Amacınız bir boru hattına standart çıktıya yazılanları göndermek olsaydı, o zaman kullanarak catuygun olacaktır Kedi Ödülü Yararsız Kullanımı beri, cat file | pipeline(burada pipelineherhangi bir boru hattı için duruyor) daha verimli olarak yapılabilir <file pipeline. Fakat yine de, sizin ifadelerinizden bunun sizin niyetiniz olmadığını anlıyorum.

Bu yüzden endişelendiğin şey o kadar net değil. Yazmak için catçok uzun bulursanız , bir veya iki karakterli takma ad tanımlayabilirsiniz (standart Unix'te kullanılmayan kalan birkaç isim vardır). Ancak catişe yaramaz döngüleri harcayan endişeleriniz varsa, yapmamalısınız.

nullArgüman almayan ve standart girdiyi standart çıktıya (boru hatları için nötr nesne) kopyalayan bir program olsaydı , istediğinizi yapabilirsiniz <file null. Böyle bir program yoktur, ancak yazması kolay olur (yalnızca bir satırlık mainişlevli bir C programı işi yapabilir), ancak catargüman olmadan çağrı yapmak (ya cat -da açık olmak istiyorsanız) bunu yapar.

Bir olsaydı nocattam olarak bir dosya ismi argümanı programı yapamam, eğer şikayet, dosyayı açmaya çalışırsa, aksi takdirde, o sizin için soruyorsunuz sadece ne olacağını standart çıkışa dosyadan kopyalamak ilerler. nullDosyayı açmak, test etmek ve muhtemelen şikayette bulunmak gibi ana işlerden yazmak biraz daha zordur (titizseniz, tam olarak bir argüman olduğuna dair bir test eklemek ve başka türlü şikayet etmek de isteyebilirsiniz). Fakat yine de cat, şimdi tek bir argümanla sağlanan, sadece bunu yapar, bu nedenle herhangi bir nocatprograma gerek yoktur .

nocatProgramı yazmayı başardıktan sonra , neden tek bir tartışmada durdun? Kodu bir döngüye sokmak for(;*argp!=NULL;++argp)gerçekten hiç çaba sarf etmiyor, ikiliye en fazla birkaç makine talimatı ekliyor ve yanlış sayıda argümandan (daha fazla talimatı saklayan) şikayet etmekten kaçınıyor. Voilà cat, birleştirici dosyaların ilkel bir sürümü . (Dürüst olmak gerekirse, biraz düzenlemelisiniz, böylece argümanlar olmadan aynı şekilde davranırlar null.)

Tabii ki gerçek catprogramda, her zaman yaptıkları için birkaç çan ve ıslık eklediler. Ancak öz, catmaliyetlerin “birleştirilmesi” özelliğinin , ne programcı ne de makineyi yürüten makine için gerçekten hiç çaba sarfetmemesidir. Bu tür programların yokluğunu catvurguladığı nullve nocataçıkladığı gerçeği . catSonuç bir boru hattına girerse tek bir argüman kullanmaktan kaçının , ancak sadece terminaldeki dosya içeriğini göstermek için kullanılıyorsa, bağlantılı olduğum sayfa bile bunun yararlı bir kullanım olduğunu kabul eder, bu catyüzden tereddüt etmeyin.


Bunu test edebilir catgerçekten hypthetical etrafında basit bir döngü tarafından uygulanmaktadır nocatarayarak işlevselliği catyerine hemen bu dosya var olmadığını şikayet yerine,: Bir geçersiz ad değil, birinci konumda aralarında birkaç dosya adları ile catilk önce gelen döker geçerli dosyalar ve ardından geçersiz dosya hakkında şikayetler (en azından kedimin davranış şekli budur).


7

altında zshdenemede

<file

Bir dosyayı basmanın en kısa yolu olduğuna inanıyorum. 'Hidden' kullanır cat(veya morestdout bir terminal ise), ancak yazdırma için kullanılan komut READNULLCMDdoğrudan komut adıyla veya hatta bazı fonksiyonlarla güvenle üzerine yazabileceğiniz değişkenle kontrol edilir . Örneğin, satır numaralandırmalı dosyaları yazdırmak için:

numcat() { nl -s'> ' -w2 - }
READNULLCMD=numcat
<file

5

POSIX, kediyi şöyle tanımlar :

ADI

cat - dosyaları birleştirmek ve yazdırmak

ÖZET

kedi [-u] [dosya ...]

AÇIKLAMA

Cat programı dosyaları sırayla okuyacak ve içeriklerini standart sıraya aynı sırayla yazacaktır.

Bu yüzden burada birleştirmek sırayla dosyaları okumak anlamına gelir .


5

Bunun çok gergin bir soru olduğunu biliyorum. Teknik olarak, bir dosyanın içeriğini bir stdoutbirleştirme şekli olduğu için yazdırmak anlamlıdır cat. Bunun printfanlamsal olarak verileri biçimlendirmek ve yazdırmak için tasarlandığını unutmayın . Bash ayrıca girdilerin ve çıktıların dosyalara yönlendirilmesi için sözdizimi sağlar. Bunların bir kombinasyonu bunu üretebilir:

printf '%s' "$(<file.txt)"

4
Özellikle dolambaçlı olmanın yanı sıra, görüntülenen komut eşdeğer değildir cat file.txt, çünkü takip eden yeni satırları kaldırır (bunu $(...)yapar).
Marc van Leeuwen

+1, iyi yakalayış. Bunu bilmiyordum.
James M. Lay

3

Yerleşikleri kullanmak bashve alt işlem oluşturmayı önleme:

{ while IFS='' read -rd '' _bcat_; do printf '%s\0' "${_bcat_}"; done; printf '%s' "${_bcat_}"; unset _bcat_; } <'/path/to/file'

IFSsadece readkomuta uygulanacak , bu nedenle global IFSdeğişiklikleriniz için endişelenmeyin .

Boş karakterleri işlemek için gerekli döngü (Stéphane Chazelas sayesinde).

Bu dosya büyük dosyalar için uygun değildir, çünkü dosya içeriği önce değişkene (yani hafızaya) okunur. BTW Bu şekilde 39M metin dosyasını yazdırmayı denedim ve bash bellek kullanımı 5M'yi geçmedi, bu nedenle bu durumdan emin değilim.

Ayrıca yavaş yavaş ve CPU verimsiz: Aynı 39M dosya için% 100 tek çekirdekli kullanımı ile ~ 3 dakika sürdü.

Büyük dosyalar veya ikili dosyalar için daha iyi, cat '/path/to/file'hatta dd if='/path/to/file' bs=1Mmümkün olsa bile .


1
Ayrıca pv -qhangi Linux'ta splice()hangi stdin / stdout türleri için performansları artıracağını da inceleyebilirsiniz.
Stéphane Chazelas,

1

Sadece bir gösteri olarak yapabilirsin.

cp foo /dev/stdout
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.