Bir uçlu dosyayı Bash betiğindeki bir dosyaya nasıl yazabilirim?


Yanıtlar:


1072

Gelişmiş Bash-Komut Dosyası Kılavuzu Bölüm 19. Burada Belgeler .

İçeriği bir dosyaya yazacak bir örnek /tmp/yourfilehere

cat << EOF > /tmp/yourfilehere
These contents will be written to the file.
        This line is indented.
EOF

Son 'EOF' (The LimitString) kelimesinin önünde boşluk olmamalıdır, çünkü bu LimitStringtanınmayacaktır.

Bir kabuk komut dosyasında, kodu okunabilir hale getirmek için girintiyi kullanmak isteyebilirsiniz, ancak bu, burada belgenizdeki metne girinti eklemek için istenmeyen bir etkiye sahip olabilir. Bu durumda, kullanım <<-(tire tarafından takip) (sekmeyi lider devre dışı bırakmak için Not size gerekecek Bunu test etmek olduğunu bir sekme karakteri ile lider boşluk yerine burada gerçek sekme karakterleri yazdırmak olamaz çünkü.)

#!/usr/bin/env bash

if true ; then
    cat <<- EOF > /tmp/yourfilehere
    The leading tab is ignored.
    EOF
fi

Metindeki değişkenleri yorumlamak istemiyorsanız, tek tırnak kullanın:

cat << 'EOF' > /tmp/yourfilehere
The variable $FOO will not be interpreted.
EOF

Yorumlu yazıyı bir komut satırından geçirmek için:

cat <<'EOF' |  sed 's/a/b/'
foo
bar
baz
EOF

Çıktı:

foo
bbr
bbz

... ya da yorumlu yazıyı aşağıdakileri kullanarak bir dosyaya yazmak için sudo:

cat <<'EOF' |  sed 's/a/b/' | sudo tee /etc/config_file.conf
foo
bar
baz
EOF

11
Bash'e bile ihtiyacınız yok, bu özellik Bourne / Korn / POSIX mermilerinde de var.
Janus Troelsen

5
ne hakkında <<<, ne denir?
Jürgen Paul

18
@PineappleUndertheSea <<<'Burada Dizeler' olarak adlandırılır. Like kodu tr a-z A-Z <<< 'one two three'dizeyle sonuçlanır ONE TWO THREE. En fazla bilgi en.wikipedia.org/wiki/Here_document#Here_strings
Stefan Lasiewski

8
Son EOF da bundan sonra herhangi bir boşluk içermemelidir . En azından bash, bu sınırlayıcı olarak tanınmaz
carpii

10
Bu özel heredoc yerine içeren ikameler daha hazır içeriği olarak tasarlanmıştır, bu olmalıdır <<'EOF'yerine <<EOF.
Charles Duffy

152

Kullanmak catve G / Ç yönlendirmesi teeyerine, bunun yerine kullanmak yararlı olabilir :

tee newfile <<EOF
line 1
line 2
line 3
EOF

Daha özlüdür, ayrıca yönlendirme operatörünün aksine, sudoroot izinlerine sahip dosyalara yazmanız gerekirse birleştirilebilir .


18
Bu > /dev/nulldosyanın içeriğini oluşturulduğunda stdout için görüntülenmesini önlemek için ilk satırın sonuna eklemeyi öneririm .
Joe Carroll

11
Doğru, ancak çözümünüz sudo, kısalığı yüzünden değil , onunla uyumluluğu nedeniyle bana hitap etti :-)
Joe Carroll

2
Varolan bir dosyaya eklemek için bu yöntemi nasıl kullanırsınız?
MountainX

5
@MountainX Kontrol edin man tee. -aÜzerine yazmak yerine eklemek için bayrağı kullanın .
Livven

3
Bazen daha bunun gibi I nezaret gerektiğini bir yapılandırma komut dosyası kullanım için çünkü o içeriklerini yazdırır.
Alois Mahdal

59

Not:

Soru (burada bir belgenin (aka heredoc ) bash komut dosyasındaki bir dosyaya nasıl yazılır? ) Sorusunun (en az) 3 ana bağımsız boyutu veya alt sorusu vardır:

  1. Mevcut bir dosyanın üzerine yazmak, mevcut bir dosyaya eklemek mi yoksa yeni bir dosyaya yazmak mı istiyorsunuz?
  2. Kullanıcınız veya başka bir kullanıcı (ör. root) Dosyanın sahibi mi?
  3. Heredoc'unuzun içeriğini tam anlamıyla yazmak mı, yoksa heredocunuzdaki değişken referansları yorumlamak mı istiyorsunuz?

(Önemli olduğunu düşünmediğim diğer boyutlar / alt sorgular da var. Bunları eklemek için bu cevabı düzenlemeyi düşünün!) Burada, yukarıda listelenen sorunun boyutlarının çeşitli farklı sınırlayıcı tanımlayıcılarla daha önemli kombinasyonlarından bazıları var - hiçbir şey yok kutsal EOF, sınırlayıcı tanımlayıcı olarak kullandığınız dizenin yorumlu metin içinde olmadığından emin olun :

  1. Heredoc içindeki değişken referansları değiştirerek, sahip olduğunuz mevcut bir dosyanın üzerine yazmak (veya yeni bir dosyaya yazmak) için:

    cat << EOF > /path/to/your/file
    This line will write to the file.
    ${THIS} will also write to the file, with the variable contents substituted.
    EOF
  2. Heredoc içindeki değişken referansları değiştirerek, sahip olduğunuz mevcut bir dosyayı eklemek (veya yeni bir dosyaya yazmak) için:

    cat << FOE >> /path/to/your/file
    This line will write to the file.
    ${THIS} will also write to the file, with the variable contents substituted.
    FOE
  3. Heredoc'un gerçek içeriği ile mevcut bir dosyanın üzerine yazmak (veya yeni bir dosyaya yazmak) için:

    cat << 'END_OF_FILE' > /path/to/your/file
    This line will write to the file.
    ${THIS} will also write to the file, without the variable contents substituted.
    END_OF_FILE
  4. Heredoc'un gerçek içeriğiyle varolan bir dosyayı eklemek (veya yeni bir dosyaya yazmak) için:

    cat << 'eof' >> /path/to/your/file
    This line will write to the file.
    ${THIS} will also write to the file, without the variable contents substituted.
    eof
  5. Yorumlu metin içinde değişken referansların yerini alarak, root'a ait mevcut bir dosyanın üzerine yazmak (veya yeni bir dosyaya yazmak) için:

    cat << until_it_ends | sudo tee /path/to/your/file
    This line will write to the file.
    ${THIS} will also write to the file, with the variable contents substituted.
    until_it_ends
  6. Kullanıcı = foo'ya ait varolan bir dosyayı heredoc'un gerçek içeriği ile eklemek (veya yeni bir dosyaya yazmak) için:

    cat << 'Screw_you_Foo' | sudo -u foo tee -a /path/to/your/file
    This line will write to the file.
    ${THIS} will also write to the file, without the variable contents substituted.
    Screw_you_Foo

# 6 en iyisidir. Ancak # 6 ile mevcut dosyanın içeriğinin üzerine nasıl yazıyorsunuz?
Aleksandr Makov

2
@Aleksandr Makov: # 6 ile mevcut dosyanın içeriğinin üzerine nasıl yazıyorsunuz? Omit -a== --append; yani, tee -a-> tee. Bkz. info tee(Burada alıntı yaparım, ancak yorum işaretlemesi çok sınırlıdır.)
TomRoche

1
# 6 yerine kedi ve boru kullanmak için bir fayda var mı sudo tee /path/to/your/file << 'Screw_you_Foo'?
codemonkee

Neden ekli örnek FOEyerine EOF?
becko

2
@becko: etiketin sadece bir etiket olduğunu göstermek için. Her örnekte farklı bir etiket kullandığımı unutmayın.
TomRoche

41

@ Livven'ın cevabı üzerine inşa etmek için bazı yararlı kombinasyonlar.

  1. değişken ikame, önde gelen sekme korunur, dosyanın üzerine yazılır, stdout'a yankı

    tee /path/to/file <<EOF
    ${variable}
    EOF
  2. değişken değiştirme yok , önde gelen sekme korunuyor, dosyanın üzerine yaz, stdout'a yankı

    tee /path/to/file <<'EOF'
    ${variable}
    EOF
  3. değişken değiştirme, önde gelen sekme kaldırıldı , dosyanın üzerine yaz, stdout'a yankı

    tee /path/to/file <<-EOF
        ${variable}
    EOF
  4. değişken ikame, önde gelen sekme korunur, dosyaya ekle, stdout'a yankı

    tee -a /path/to/file <<EOF
    ${variable}
    EOF
  5. değişken ikame, önde gelen sekme korunmuş, dosyanın üzerine yaz, stdout'a yankı yok

    tee /path/to/file <<EOF >/dev/null
    ${variable}
    EOF
  6. yukarıdakiler de kombine sudoedilebilir

    sudo -u USER tee /path/to/file <<EOF
    ${variable}
    EOF

16

Kök izinleri gerektiğinde

Hedef dosya için kök izinleri gerektiğinde, aşağıdakiler |sudo teeyerine şunu kullanın >:

cat << 'EOF' |sudo tee /tmp/yourprotectedfilehere
The variable $FOO will *not* be interpreted.
EOF

Buradaki dokümanlara değişkenler iletmek mümkün mü? $ FOO'nun yorumlanması için bunu nasıl elde edebilirsiniz?
user1527227

@ Buradaki örnekte dosyası olarak user1527227 diyor: değişken $ FOO olacak değil yorumlanmalıdır.
Serge Stroobandt

Aşağıda bu cevabı Stefan Lasiewski'nin cevabı ile birleştirmeye ve düzenlemeye çalıştım .
TomRoche

3
@ user1527227 EOF'u tek tırnak içine almayın. Sonra $ FOO yorumlanacak.
imnd_neel

11

Bu sorunu yaşayabilecek gelecekteki insanlar için aşağıdaki format işe yaradı:

(cat <<- _EOF_
        LogFile /var/log/clamd.log
        LogTime yes
        DatabaseDirectory /var/lib/clamav
        LocalSocket /tmp/clamd.socket
        TCPAddr 127.0.0.1
        SelfCheck 1020
        ScanPDF yes
        _EOF_
) > /etc/clamd.conf

6
Parantezlere gerek yok: cat << END > afileardından yorumlu metin mükemmel çalışıyor.
glenn jackman

Teşekkürler, bu aslında karşılaştığım başka bir sorunu çözdü. Buradaki birkaç dokümandan sonra bazı sorunlar vardı. Bence yukarıdaki tavsiyede olduğu gibi, parens ile ilgili olduğunu düzeltti.
Joshua Enfield

2
Bu işe yaramaz. Çıkış yeniden yönlendirmesinin cat, kabul edilen yanıtta gösterildiği gibi başlayan satırın sonunda olması gerekir .
sonraki duyuruya kadar duraklatıldı.

2
@DennisWilliamson İşe yarıyor, parens bunun için. Bütün catbir alt kabuğun içinde çalışır ve alt kabuğun tüm çıktıları dosyaya yönlendirilir
Izkata

2
@Izkata: Bu cevabın düzenleme geçmişine bakarsanız, yorumumu yapmadan önce parantez kaldırıldı ve daha sonra tekrar eklendi. glenn jackman'ın (ve benim) yorumu geçerlidir.
sonraki duyuruya kadar duraklatıldı.

3

Örnek olarak kullanabilirsiniz:

İlk olarak (ssh bağlantısı yapmak):

while read pass port user ip files directs; do
    sshpass -p$pass scp -o 'StrictHostKeyChecking no' -P $port $files $user@$ip:$directs
done <<____HERE
    PASS    PORT    USER    IP    FILES    DIRECTS
      .      .       .       .      .         .
      .      .       .       .      .         .
      .      .       .       .      .         .
    PASS    PORT    USER    IP    FILES    DIRECTS
____HERE

İkincisi (komutları yürütmek):

while read pass port user ip; do
    sshpass -p$pass ssh -p $port $user@$ip <<ENDSSH1
    COMMAND 1
    .
    .
    .
    COMMAND n
ENDSSH1
done <<____HERE
    PASS    PORT    USER    IP
      .      .       .       .
      .      .       .       .
      .      .       .       .
    PASS    PORT    USER    IP    
____HERE

Üçüncü olarak (komutları yürütmek):

Script=$'
#Your commands
'

while read pass port user ip; do
    sshpass -p$pass ssh -o 'StrictHostKeyChecking no' -p $port $user@$ip "$Script"

done <<___HERE
PASS    PORT    USER    IP
  .      .       .       .
  .      .       .       .
  .      .       .       .
PASS    PORT    USER    IP  
___HERE

Dördüncü (değişkenleri kullanarak):

while read pass port user ip fileoutput; do
    sshpass -p$pass ssh -o 'StrictHostKeyChecking no' -p $port $user@$ip fileinput=$fileinput 'bash -s'<<ENDSSH1
    #Your command > $fileinput
    #Your command > $fileinput
ENDSSH1
done <<____HERE
    PASS    PORT    USER    IP      FILE-OUTPUT
      .      .       .       .          .
      .      .       .       .          .
      .      .       .       .          .
    PASS    PORT    USER    IP      FILE-OUTPUT
____HERE

-1

Girintili bir komut dosyasında kısaltma, okunabilirlik ve sunum için bu yöntemi seviyorum:

<<-End_of_file >file
       foo bar
End_of_file

→       Bir tabkarakter nerede .

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.