¿Cómo puedo escribir un heredoc en un archivo en el script Bash?

¿Cómo puedo escribir un documento aquí en un archivo en el script Bash?

Lea la Guía Avanzada de Bash-Scripting Capítulo 19. Aquí Documentos .

Aquí hay un ejemplo que escribirá los contenidos en un archivo en /tmp/yourfilehere

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

Tenga en cuenta que el ‘EOF’ final (The LimitString ) no debe tener ningún espacio en blanco delante de la palabra, porque significa que LimitString no será reconocido.

En un script de shell, es posible que desee utilizar una sangría para hacer que el código sea legible, sin embargo, esto puede tener el efecto indeseable de sangrar el texto dentro de su documento aquí. En este caso, use <<- (seguido de un guion) para deshabilitar las tabs delanteras (tenga en cuenta que para probar esto deberá reemplazar el espacio en blanco inicial con un carácter de tabulación , ya que no puedo imprimir los tabuladores reales aquí).

 #!/usr/bin/env bash if true ; then cat <<- EOF > /tmp/yourfilehere The leading tab is ignored. EOF fi 

Si no desea interpretar las variables en el texto, utilice comillas simples:

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

Para canalizar el heredoc a través de una canalización de comandos:

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

Salida:

 foo bbr bbz 

... o para escribir el heredoc en un archivo usando sudo :

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

En lugar de usar el cat y la redirección de E / S, podría ser útil usar una tee lugar:

 tee newfile < 

Es más conciso, además, a diferencia del operador de redirección, se puede combinar con sudo si necesita escribir en archivos con permisos de raíz.

Nota:

  • lo siguiente condensa y organiza otras respuestas en este hilo, especialmente el excelente trabajo de Stefan Lasiewski y Serge Stroobandt
  • Lasiewski y yo recomendamos el capítulo 19 (aquí los documentos) en la guía avanzada Bash-Scripting

La pregunta (¿cómo escribir un documento aquí (también conocido como heredoc ) a un archivo en un script bash?) Tiene (al menos) 3 dimensiones o subasesorías independientes principales:

  1. ¿Desea sobrescribir un archivo existente, anexarlo a un archivo existente o escribir en un nuevo archivo?
  2. ¿Su propio usuario u otro usuario (p. Ej., root ) posee el archivo?
  3. ¿Desea literalmente escribir el contenido de su heredoc o hacer que bash interprete las referencias de variables dentro de su heredoc?

(Hay otras dimensiones / preguntas que no considero importantes. ¡Considere editar esta respuesta para agregarlas!) Aquí están algunas de las combinaciones más importantes de las dimensiones de la pregunta listadas arriba, con varios identificadores de delimitación diferentes – no hay nada sagrado sobre EOF , solo asegúrate de que la cadena que usas como tu identificador delimitador no ocurra dentro de tu heredoc:

  1. Para sobrescribir un archivo existente (o escribir en un archivo nuevo) que sea suyo, sustituyendo referencias de variables dentro del heredoc:

     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. Para anexar un archivo existente (o escribir en un archivo nuevo) que sea suyo, sustituyendo referencias de variables dentro del heredoc:

     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. Para sobrescribir un archivo existente (o escribir en un nuevo archivo) que posea, con los contenidos literales del heredoc:

     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. Para agregar un archivo existente (o escribir en un archivo nuevo) que usted posee, con los contenidos literales del 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. Para sobrescribir un archivo existente (o escribir en un archivo nuevo) propiedad de root, sustituyendo las referencias de variables dentro de 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. Para agregar un archivo existente (o escribir en un nuevo archivo) propiedad de user = foo, con los contenidos literales del 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 

Para construir sobre la respuesta de @ Livven, aquí hay algunas combinaciones útiles.

  1. sustitución de variables, pestaña principal retenida, archivo de sobrescritura, eco de stdout

     tee /path/to/file < 
  2. sin sustitución de variables , pestaña principal retenida, archivo de sobrescritura, eco de stdout

     tee /path/to/file <<'EOF' ${variable} EOF 
  3. sustitución de variables, pestaña inicial eliminada , archivo de sobrescritura, eco de stdout

     tee /path/to/file <<-EOF ${variable} EOF 
  4. sustitución de variables, pestaña principal retenida, añadir a archivo , eco a stdout

     tee -a /path/to/file < 
  5. sustitución de variables, pestaña principal retenida, archivo de sobrescritura, sin eco a stdout

     tee /path/to/file </dev/null ${variable} EOF 
  6. lo anterior también se puede combinar con sudo

     sudo -u USER tee /path/to/file < 

Cuando se requieren permisos de raíz

Cuando se requieren permisos de raíz para el archivo de destino, use |sudo tee lugar de > :

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

Para las personas futuras que puedan tener este problema, el siguiente formato funcionó:

 (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 

Como instancia, podrías usarlo:

Primero (haciendo conexión 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 

Segundo (ejecutar comandos):

 while read pass port user ip; do sshpass -p$pass ssh -p $port $user@$ip < 

Tercero (ejecutar comandos):

 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 

Adelante (usando variables):

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