Cómo cat cat <> un archivo que contiene el código?

Quiero imprimir código en un archivo usando cat <> :

 cat <> brightup.sh !/bin/bash curr=`cat /sys/class/backlight/intel_backlight/actual_brightness` if [ $curr -lt 4477 ]; then curr=$((curr+406)); echo $curr > /sys/class/backlight/intel_backlight/brightness; fi EOF 

pero cuando miro la salida del archivo, obtengo esto:

 !/bin/bash curr=1634 if [ -lt 4477 ]; then curr=406; echo > /sys/class/backlight/intel_backlight/brightness; fi 

Traté de poner comillas simples, pero la salida también lleva las comillas simples con ella. ¿Cómo puedo evitar este problema?

Solo necesitas un cambio mínimo; cite una sola vez el delimitador aquí documento después de << .

 cat <<'EOF' >> brightup.sh 

o una barra diagonal inversa equivalente: escapar de ella:

 cat <<\EOF >>brightup.sh 

Sin citar, el documento aquí se someterá a sustitución de variables, se evaluarán los backticks, etc., como descubriste.

Si necesita expandir algunos, pero no todos, valores, necesita escaparse individualmente de los que desea evitar.

 cat <>brightup.sh #!/bin/sh # Created on $(date # : <<-- this will be evaluated before cat;) echo "\$HOME will not be evaluated because it is backslash-escaped" EOF 

Producirá

 #!/bin/sh # Created on Fri Feb 16 11:00:18 UTC 2018 echo "$HOME will not be evaluated because it is backslash-escaped" 

Como lo sugiere @fedorqui , aquí está la sección relevante de man bash :

Aquí documentos

Este tipo de redirección ordena al shell que lea la entrada de la fuente actual hasta que se vea una línea que solo contenga un delimitador (sin espacios en blanco al final). Todas las líneas leídas hasta ese punto se usan luego como entrada estándar para un comando.

El formato de los documentos aquí es:

  <<[-]word here-document delimiter 

No se realiza expansión de parámetros, sustitución de comandos, expansión aritmética o expansión de nombre de ruta en palabra. Si se citan los caracteres de la palabra, el delimitador es el resultado de la eliminación de la cita en la palabra, y las líneas en el documento aquí no se expanden. Si la palabra no está citada, todas las líneas del documento aquí están sujetas a expansión de parámetros, sustitución de comandos y expansión aritmética . En este último caso, la secuencia de caracteres \ se ignora, y \ se debe usar para citar los caracteres \, $ y `.

O bien, usando sus marcadores EOF, debe citar el marcador inicial para que la expansión no se realice:

 #-----v---v------ cat <<'EOF' >> brightup.sh #!/bin/bash curr=`cat /sys/class/backlight/intel_backlight/actual_brightness` if [ $curr -lt 4477 ]; then curr=$((curr+406)); echo $curr > /sys/class/backlight/intel_backlight/brightness; fi EOF 

IHTH

Esto debería funcionar, simplemente lo probé y funcionó como se esperaba: no hubo expansión, sustitución ni lo que sucedió.

 cat <<< ' #!/bin/bash curr=`cat /sys/class/backlight/intel_backlight/actual_brightness` if [ $curr -lt 4477 ]; then curr=$((curr+406)); echo $curr > /sys/class/backlight/intel_backlight/brightness; fi' > file # use overwrite mode so that you don't keep on appending the same script to that file over and over again, unless that's what you want. 

Usar lo siguiente también funciona.

 cat <<< ' > file ... code ...' 

Además, vale la pena señalar que cuando se utilizan heredocs, como << EOF , ocurre sustitución y expansión de variables, etc. Entonces, haz algo como esto:

 cat << EOF > file cd "$HOME" echo "$PWD" # echo the current path EOF 

siempre resultará en la expansión de las variables $HOME y $PWD . Entonces, si su directorio principal es /home/foobar y la ruta actual es /home/foobar/bin , el file se verá así:

 cd "/home/foobar" echo "/home/foobar/bin" 

en lugar de lo esperado:

 cd "$HOME" echo "$PWD"