Cat komutu ve yankı


14

Eko çıktısını bir dosyanın içeriğiyle birleştirmek istiyorum. Aşağıdaki komedi denedim:

echo "abc" | cat 1.txt > 2.txt

ancak 2.txtdosya yalnızca içindeki içeriği içerir 1.txt. Neden çalışmıyor?


3
Programlar, catyalnızca dosya adı bağımsız değişkenleri yoksa standart girdiden okur gibi .
Barmar

Yanıtlar:


23

Çünkü çalışmıyor catPiponuzu sırayla programı okumak için talimat değildi echostandart girdiden programın çıktısını.

Sen kullanabilirsiniz -standart giriş belirtmek için bir sözde dosya adı olarak cat. Gönderen man catbir msys2 yüklemesinde:

EXAMPLES
       cat f - g
              Output f's contents, then standard input, then g's contents.

O zaman dene

echo "abc" | cat - 1.txt > 2.txt

yerine.


21

Başkaları tarafından belirtildiği gibi, orijinal komutunuz cat 1.txtstandart girdisini göz ardı ettiği için başarısız olur . Ya onun ilk argümanı ( cat - 1.txt) olması gerektiğini belirtin veya yönlendirmek ve birlikte yönlendirmek için blok yönlendirmeyi kullanın . Zekâ için:echo abc cat 1.txt

{ echo abc; cat 1.txt; } > 2.txt 

Kılavuzdan ilgili alıntı ( man bash):

Bileşik Komutlar Bileşik
komut aşağıdakilerden biridir. Çoğu durumda , bir komutun açıklamasındaki bir liste , komutun geri kalanından bir veya daha fazla yeni satır ile ayrılabilir ve arkasından noktalı virgül yerine bir yeni satır gelebilir.

(liste)

    listesi bir alt kabuk ortamında yürütülür (aşağıdaki KOMUT YÜRÜTME ORTAMI'na bakın). Kabuğun ortamını etkileyen değişken atamaları ve yerleşik komutlar, komut tamamlandıktan sonra geçerli olmaz. Dönüş durumu listenin çıkış durumudur.

{liste; }

    liste sadece geçerli kabuk ortamında yürütülür.  liste bir satırsonu veya noktalı virgülle sonlandırılmalıdır. Bu, grup komutu olarak bilinir . Dönüş durumu listenin çıkış durumudur . Meta karakterler aksine o Not (ve ), {ve }vardır ayrılmış sözcükler ve ayrılmış bir kelime tanınacak izin nerede gerçekleşmelidir. Sözcük kesintisine neden olmadıkları için , boşluk veya başka bir kabuk metakarakteriyle listeden ayrılmalıdır .

İlk seçenek (alt kabuk ortamı), çoğu sizin senaryonuzla ilgisi olmasa da bir sürü yan etkiye sahiptir; ancak, bir grup komutun çıktısını yeniden yönlendirmek için tek ihtiyacınız varsa, burada Seçenek # 2 (grup komutu) tercih edilir.


7
( echo "abc"; cat 1.txt ) > 2.txt

Yankı çıkışını kediye bağladınız, ancak kedinin giriş için bir faydası yoktu ve yok sayıldı. Şimdi komutlar birbiri ardına çalışır ve çıktıları gruplandırılır (parantez) ve 2.txt'ye yönlendirilir.


1
Bu cevap, nasıl çalıştığını ve OP'nin orijinal girişiminin neden çalışmadığını açıklayarak geliştirilebilir .
Bob

Tamam, denedi.
Gerard

5
Burada bir alt kabuk açıkça gerekli değildir, belki bir grup komutu kullanmak daha iyi olacaktır. Daha fazla ayrıntı için cevabıma bakın.
Nubarke

Ah, ama asla bash kullanmam.
Gerard

1
@ GerardH.Pille: Daniel'in yanıtı alıntılanırken bash(1), her POSIX uyumlu kabuğun desteklemesi gereken davranışı açıklar .
G-Man,

2

Komutunuz cat 1.txtçıktı ile hiçbir şey yapmıyor echo "abc".

Bunun yerine: (echo "abc"; cat 1.txt) > 2.txt her iki komutun çıktısını 2.txt dosyasına yazar.


Bu cevap önerilen alternatifin nasıl çalıştığını açıklayarak geliştirilebilir.
Bob

1

Herhangi bir POSIX kabuğunda aşağıdakiler cat fileiçin girdi olarak kullanmak üzere komut ikamesini kullanabilirsiniz echo:

echo $(cat file1.txt) "This Too"

Bash'te işlem ikamesini ve echo'yu başka bir "dosya" catolarak aşağıdaki gibi kullanabilirsiniz:

cat file1.txt <(echo This Too)

ve sonra çıktıyı uygun gördüğünüz şekilde yönlendirin veya yönlendirin.

Diğer tüm cevapların söylediği gibi, kedi bakılacak bir dosya varsa stdin'i yok sayar. (Daniel & mvw'nin cevaplarını da beğendim, onlar için +1)


1
Bu cevap, OP'nin orijinal girişiminin neden çalışmadığını (ve bunun yerine bunun neden gerekli olduğunu) açıklayarak geliştirilebilir.
Bob

1
<(command)İnşaat bir bash uzantısıdır. POSIX değildir, bu nedenle yürütülmesi gereken komut dosyalarına güvenemezsiniz /bin/sh.
Rhialto, Monica

0

Sadece bir tahmin, ama bir takma ad veya işlev için iyi bir aday olan tekrarlanabilir bir süreciniz var gibi görünüyor. Takma adlar genellikle bağımsız değişken olarak tek bir giriş akışında kısaltma gibi bash komutlarını çağırmak için kullanılan kısa yollardır.

alias hg="history | grep"

Bununla birlikte, bu durumda, birden çok, ayrık (2) giriş akışının yanı sıra çoklu bash komutlarını birleştirdiğiniz için bir işlev daha okunabilir olacaktır. İlki bir dize, diğeri bir dosya yolu olmak üzere iki argümanınız var. Sonunda, sonucun stdout çıktı akışına yazılmasını istiyorsunuz.

CLI isteminden şunu yazın:

# ecat()        
{
echo ${1}
cat ${2}
}

Fonksiyonunuza unutulmaz olan ecat adı verilir.

Şimdi şu şekilde çağırabilirsiniz:

ecat "abc" 1.txt

Eklemek için stdout'a farklı bir çıkış hedefi sağlamanız yeterlidir:

ecat "abc" 1.txt >> 2.txt

Ekle yönlendirme operatörü '>>' çıktıyı belirtilen dosyanın sonuna ekler.

Beğendiyseniz, tekrar kullanmak için ~ / .bashrc dosyanıza ekleyin.

declare -f ecat >> ~/.bashrc

Bu ayrıca işlev tanımınız içinde süsleyebileceğiniz vb. Anlamına gelir.

Ayrıca ~ / .bashrc dosyasına ekleyerek dosyaların üzerine yazılmasını önlemek için iyi bir fikir

set noclobber

2
Sizin işlevi düzgün davranmaya için, kullanması gereken "$1"ve "$2". Bu bağlamda, kıvırcık parantezlerin hiçbir faydası yoktur. Gördüğünü ${name}düşündüğün anlamına gelmez… .
G-Man,

1
noclobberÖneri eldeki soruya nasıl cevap veriyor? (Ayrıca, bunun iyi bir tavsiye olduğuna ikna oldum - küresel davranışı değiştirmek, varsayılanları göz önünde bulundurarak oluşturulan komut dosyalarını / tavsiyeleri / uygulamaları kırma eğilimindedir).
Charles Duffy

0

Aşağıdaki kod da çalışır:

echo abc >> 1.txt && cat 1.txt > 2.txt

Çıktısı yankı abc ile 1.TXT eklenecektir >> Bundan sonra && hangi irade komutları sonraki seti çalıştırmak için bunu söyleyecektir kedi 1.txt sonra çıktı o ve 2.txt . Temel olarak, ilk komutun çıktısını 1.txt'ye ekler ve sonra 1.txt çıktısını 2.txt'ye gönderir.

Önce abc'nin görünmesini istiyorsanız, aşağıdaki kodu kullanabilirsiniz:

echo abc >> 2.txt && cat 1.txt >> 2.txt

1
Koymak Bu, (1) abcen alt bölgesinin 2.txt; soru üstte istiyor. (2)  modifiye1.txt dosyası; bu kabul edilemez.
G-Man

Bunu nerede söylüyor? Ringger81, 2.txt dosyasında abc'nin görünmesini istediğini hiçbir zaman belirtmedi. Sorunun asla belirtmediği şeyleri varsayıyorsunuz.
Nasir Riley

(1) Tamam, # 1 üzerinde geçerli bir puan veriyorsunuz. Soru metninde “Bir dosyanın içeriği” önce “yankı çıktı”, bahseder ve sonra koyar iken echoönce catnumune komuta, ben asla tam olarak, varsayalım açıkça , daha önce eko çıktı istediğini söylüyor girdi dosyasının içeriği. Görünüşe göre çoğu insan bunu böyle yorumluyor. (2)  1.txtbir girdi dosyasıdır. Soru, değişiklik hakkında hiçbir şey söylemiyor 1.txt. Giriş dosyalarının değiştirilmemesi gerektiği söylenmeden gider.
G-Man

Imput dosyasını değiştirmeme konusundaki görüşünüzü anlayabilirim. İkinci kodum bunu yapmadan istenen efekti elde edecektir.
Nasir Riley

1
Bir dosyayı açmak, eklemek, kapatmak , tekrar açmak, tekrar eklemek ... bunu neden sadece bir kez açmak ve her iki işlem için yönlendirmeyi yerinde tutmak yerine?
Charles Duffy
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.