Question Comment puis-je écrire un heredoc dans un fichier dans un script Bash?


Comment puis-je écrire un document ici dans un fichier dans un script Bash?


536
2018-06-01 20:28


origine


Réponses:


Lisez le Guide avancé de script Bash Chapitre 19. Documents ici.

Voici un exemple qui écrira le contenu dans un fichier à /tmp/yourfilehere

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

Notez que la finale 'EOF' (The LimitString) ne devrait pas avoir d'espace devant le mot, car cela signifie que le LimitString ne sera pas reconnu.

Dans un script shell, vous pouvez utiliser l'indentation pour rendre le code lisible, mais cela peut avoir l'effet indésirable d'indenter le texte dans votre document ici. Dans ce cas, utilisez <<- (suivi d'un tiret) pour désactiver les onglets principaux (Remarque que pour tester cela, vous devrez remplace l'espace blanc de début par un caractère de tabulation, car je ne peux pas imprimer les caractères de tabulation réels ici.)

#!/usr/bin/env bash

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

Si vous ne voulez pas interpréter les variables dans le texte, utilisez des guillemets simples:

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

Pour diriger l'hérédoc via un pipeline de commandes:

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

Sortie:

foo
bbr
bbz

... ou écrire l'heredoc dans un fichier en utilisant sudo:

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

754
2018-06-02 03:40



À la place d'utiliser cat et la redirection d'E / S, il pourrait être utile d'utiliser tee au lieu:

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

Il est plus concis, et contrairement à l'opérateur de redirection, il peut être combiné avec sudo si vous devez écrire dans des fichiers avec des permissions root.


109
2018-06-13 17:35



Remarque:

La question (comment écrire un document ici (aka heredoc) à un fichier dans un script bash?) a (au moins) 3 principales dimensions ou sous-questions indépendantes:

  1. Souhaitez-vous remplacer un fichier existant, l'ajouter à un fichier existant ou écrire dans un nouveau fichier?
  2. Votre utilisateur ou un autre utilisateur (p. root) possède le fichier?
  3. Voulez-vous écrire littéralement le contenu de votre heredoc, ou bien bash interpréter des références variables à l'intérieur de votre heredoc?

(Il y a d'autres dimensions / sous-questions que je ne considère pas comme importantes.Prenez d'éditer cette réponse pour les ajouter!) Voici quelques-unes des combinaisons les plus importantes des dimensions de la question ci-dessus, avec différents identifiants de délimitation - il n'y a rien sacré à propos EOF, assurez-vous simplement que la chaîne que vous utilisez comme identificateur de délimitation ne pas se produire à l'intérieur de votre heredoc:

  1. Pour écraser un fichier existant (ou écrire dans un nouveau fichier) que vous possédez, en substituant des références de variables à l'intérieur de l'hérédoc:

    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. Pour ajouter un fichier existant (ou écrire dans un nouveau fichier) que vous possédez, en remplaçant les références de variables dans l'hérédoc:

    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. Pour écraser un fichier existant (ou écrire dans un nouveau fichier) que vous possédez, avec le contenu littéral de l'hérédoc:

    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. Pour ajouter un fichier existant (ou écrire dans un nouveau fichier) que vous possédez, avec le contenu littéral de l'heredoc:

    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. Pour remplacer un fichier existant (ou écrire dans un nouveau fichier) appartenant à root, en remplaçant les références de variables dans heredoc:

    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. Pour ajouter un fichier existant (ou écrire dans un nouveau fichier) appartenant à user = foo, avec le contenu littéral de l'heredoc:

    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
    

37
2017-09-18 03:11



Pour construire sur @ Livven répondre, voici quelques combinaisons utiles.

  1. substitution de variable, tabulation de tête conservée, écraser le fichier, echo vers stdout

    tee /path/to/file <<EOF
    ${variable}
    EOF
    
  2. pas de substitution de variable, onglet principal conservé, écraser le fichier, echo sur stdout

    tee /path/to/file <<'EOF'
    ${variable}
    EOF
    
  3. substitution variable, onglet principal supprimé, remplacer le fichier, echo par stdout

    tee /path/to/file <<-EOF
        ${variable}
    EOF
    
  4. substitution de variable, tabulation de tête conservée, ajouter au fichier, echo à stdout

    tee -a /path/to/file <<EOF
    ${variable}
    EOF
    
  5. substitution de variable, tabulation de tête conservée, fichier d'écrasement, pas d'écho à stdout

    tee /path/to/file <<EOF >/dev/null
    ${variable}
    EOF
    
  6. ce qui précède peut être combiné avec sudo ainsi que

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

14
2017-08-02 21:48



Pour les personnes qui pourraient avoir ce problème, le format suivant a fonctionné:

(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

12
2018-06-01 21:02



Lorsque les autorisations root sont requises

Lorsque les autorisations root sont requises pour le fichier de destination, utilisez |sudo tee au lieu de >:

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

12
2018-02-13 20:55



Par exemple, vous pouvez l'utiliser:

Premier (en faisant la connexion ssh):

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

Deuxième (commandes d'exécution):

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

Troisième (commandes d'exécution):

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

Forth (en utilisant des variables):

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

2
2018-02-16 10:17