letras - Comando de Unix para anteponer texto a un archivo
como crear archivos en linux (16)
Sustitución de procesos
Estoy sorprendido de que nadie haya mencionado esto.
cat <(echo "before") text.txt > newfile.txt
que es posiblemente más natural que la respuesta aceptada (imprimir algo y conectarlo a un comando de sustitución es lexicográficamente contraintuitivo).
... y secuestrando lo que dijo Ryan anteriormente, con una sponge
no necesitas un archivo temporal:
sudo apt-get install moreutils
<<(echo "to be prepended") < text.txt | sponge text.txt
EDITAR: Parece que esto no funciona en Bourne Shell /bin/sh
Aquí String
Usando una cadena aquí - <<<
(de nuevo, necesitas bash), puedes hacer:
<<< "to be prepended" < text.txt | sponge text.txt
¿Hay un comando de Unix para anteponer algunos datos de cadena a un archivo de texto?
Algo como:
prepend "to be prepended" text.txt
En algunas circunstancias, el texto precedente puede estar disponible solo desde stdin. Entonces esta combinación funcionará.
echo "to be prepended" | cat - text.txt | tee text.txt
Si desea omitir tee
salida en tee
, añada > /dev/null
.
Esta es una posibilidad:
(echo "to be prepended"; cat text.txt) > newfile.txt
es probable que no pueda moverse fácilmente por un archivo intermedio.
Alternativas (puede ser engorroso con el escape de shell):
sed -i ''0,/^/s//to be prepended/'' text.txt
Esto funcionará para formar la salida. El - significa entrada estándar, que se proporciona a través de la tubería de eco.
echo -e "to be prepended /n another line" | cat - text.txt
Para volver a escribir el archivo, se requiere un archivo temporal, ya que no puede regresar al archivo de entrada.
echo "to be prepended" | cat - text.txt > text.txt.tmp
mv text.txt.tmp text.txt
Otra forma de usar sed
:
sed -i.old ''1 {i to be prepended
}'' inFile
Si la línea que se debe anexar es multilínea:
sed -i.old ''1 {i/
to be prepended/
multiline
}'' inFile
Otra solución bastante directa es:
$ echo -e "string/n" $(cat file)
Prefiero la answer de Adam
Podemos hacer que sea más fácil usar sponge . Ahora no necesitamos crear un archivo temporal y cambiarle el nombre por
echo -e "to be prepended /n another line" | cat - text.txt | sponge text.txt
Probablemente no tenga nada incorporado, pero podría escribir el suyo con bastante facilidad, así:
#!/bin/bash
echo -n "$1" > /tmp/tmpfile.$$
cat "$2" >> /tmp/tmpfile.$$
mv /tmp/tmpfile.$$ "$2"
Algo así al menos ...
Realmente no me gustó ninguna de las respuestas aquí, así que construí mi propio comando: pre
.
Instalar con go:
go get -u github.com/Flaque/pre
Antepone un texto de stdin a un archivo con:
echo "some at the start" | pre myFile.txt | sponge myFile.txt
El comando no se escribe en su lugar, solo se envía a stdout, por lo que necesitará la sponge
de moreutils
al final para guardar el archivo.
Recomiendo definir una función y luego importarla y usarla cuando sea necesario.
prepend_to_file() {
file=$1
text=$2
if ! [[ -f $file ]] then
touch $file
fi
echo "$text" | cat - $file > $file.new
mv -f $file.new $file
}
Entonces úsalo así:
prepend_to_file test.txt "This is first"
prepend_to_file test.txt "This is second"
El contenido de tu archivo será entonces:
This is second
This is first
Estoy a punto de utilizar este enfoque para implementar un actualizador de registro de cambios.
Si es aceptable reemplazar el archivo de entrada :
Nota: Hacerlo puede tener efectos secundarios inesperados , en especial reemplazando un enlace simbólico con un archivo común, posiblemente terminando con diferentes permisos en el archivo, y cambiando la fecha de creación (nacimiento) del archivo .
sed -i
, como en la respuesta del Príncipe Juan Wesley , intenta al menos restaurar los permisos originales, pero se aplican las otras limitaciones .
{ printf ''line 1/nline 2/n''; cat text.txt; } > tmp.txt && mv tmp.txt text.txt
Nota: Usando un comando de grupo { ...; ... }
{ ...; ... }
es más eficiente que usar una subcadena ( (...; ...)
).
Si el archivo de entrada debe editarse en su lugar (preservando su inodo con todos sus atributos) :
Usando la venerable herramienta ed
POSIX :
Nota: ed
invariablemente lee el archivo de entrada como un todo en la memoria primero.
ed -s text.txt <<''EOF''
1i
line 1
line 2
.
w
EOF
-
-s
suprimió los mensajes de estado deed
. - Observe cómo se proporcionan los comandos a
ed
como un here-document multilínea (<<''EOF'' ... EOF
), es decir, a través de stdin . -
1i
hace1
(la 1ra línea) la línea actual y comienza el modo de inserción (i
). - Las siguientes líneas son el texto para insertar antes de la línea actual, terminada con
.
en su propia línea. -
w
escribe el resultado en el archivo de entrada (para probar, reemplacew
con,p
para imprimir solo el resultado, sin modificar el archivo de entrada).
Si te gusta vi / vim, este puede ser más tu estilo.
printf ''0i/n%s/n./nwq/n'' prepend-text | ed file
Solución:
printf ''%s/n%s'' ''text to prepend'' "$(cat file.txt)" > file.txt
Tenga en cuenta que esto es seguro en todo tipo de entradas, porque no hay expansiones. Por ejemplo, si quiere anteponer !@#$%^&*()ugly text/n/t/n
, simplemente funcionará:
printf ''%s/n%s'' ''!@#$%^&*()ugly text/n/t/n'' "$(cat file.txt)" > file.txt
La última parte que queda por considerar es la eliminación del espacio en blanco al final del archivo durante la sustitución del comando "$(cat file.txt)"
. Todas las soluciones para esto son relativamente complejas. Si desea preservar nuevas líneas al final de file.txt, consulte esto: https://.com/a/22607352/1091436
# create a file with content..
echo foo > /tmp/foo
# prepend a line containing "jim" to the file
sed -i "1s/^/jim/n/" /tmp/foo
# verify the content of the file has the new line prepened to it
cat /tmp/foo
printf ''%s/n%s/n'' "to be prepended" "$(cat text.txt)" >text.txt
sed -i.old ''1s;^;to be prepended;'' inFile
-
-i
escribe el cambio en su lugar y toma una copia de seguridad si se proporciona alguna extensión. (En este caso,.old
) -
1s;^;to be prepended;
sustituye el comienzo de la primera línea por la cadena de reemplazo dada, utilizando;
como un delimitador de comando.