Pregunta ¿Cómo agrego texto al comienzo de un archivo en Bash?


Hola, quiero anteponer el texto a un archivo. Por ejemplo, quiero agregar tareas al comienzo de un archivo todo.txt. Estoy consciente de echo 'task goes here' >> todo.txt pero eso agrega la línea al final del archivo (no es lo que quiero).


228


origen


Si no existe una manera eficiente de hacer eso para archivos grandes: unix.stackexchange.com/questions/87772/... - Ciro Santilli 新疆改造中心 六四事件 法轮功


Respuestas:


echo 'task goes here' | cat - todo.txt > temp && mv temp todo.txt

o

sed -i '1s/^/task goes here\n/' todo.txt

o

sed -i '1itask goes here' todo.txt

304



¡el primero funciona genial! te importaría explicar la lógica? No estoy particularmente seguro de cómo interpretar la sintaxis. - user479534
@ user8347: Pipe (|) el mensaje (echo '...') a cat que usa - (entrada estándar) como el primer archivo y todo.txt como el segundo. cat conCATenates múltiples archivos. Enviar la salida (>) a un archivo llamado temp. Si no hay errores (&&) de cat luego cambie el nombre (mv) el temp archivo de nuevo al archivo original (todo.txt) - Dennis Williamson
No sabía acerca de esta posible sintaxis en el último ejemplo de sed, ¿alguien me puede decir cuál es el nombre de este tipo de sintaxis para poder buscar más sobre él? - Kira
@Kira: El 1 significa hacer el siguiente comando solo en la línea uno del archivo y i el comando es insertar. Busque en la página del manual bajo la sección "Direcciones" y en la sección "Comandos de dirección cero o uno". - Dennis Williamson
@Terrance: si su sed comando se ve algo así (insertando una pestaña principal): '1i\tSome Text', es posible que deba duplicar la barra diagonal inversa. De lo contrario, tu dialecto de sed puede que no reconozca \t como pestaña - Dennis Williamson


Una opción más simple en mi opinión es:

echo -e "task goes here\n$(cat todo.txt)" > todo.txt

Esto funciona porque el comando dentro de $(...) se ejecuta antes todo.txt se sobrescribe con > todo.txt

Mientras que las otras respuestas funcionan bien, me parece mucho más fácil de recordar porque uso eco y gato todos los días.

EDITAR: Esta solución es una muy mala idea si hay alguna barra invertida en todo.txt, porque gracias a la -e flag echo los interpretará. Otra forma, mucho más sencilla, de obtener nuevas líneas en la cadena de prefacio es ...

echo "task goes here
$(cat todo.txt)" > todo.txt

... simplemente para usar nuevas líneas. Claro, ya no es de una sola línea, pero de manera realista tampoco fue de una sola línea. Si está haciendo esto dentro de un script, y está preocupado por la sangría (por ejemplo, está ejecutando esto dentro de una función), existen algunas soluciones para que esto quede bien, que incluye pero no se limita a:

(echo 'task goes here' && cat todo.txt) > todo.txt
echo 'task goes here'$'\n'"$(cat todo.txt)" > todo.txt

Además, si le importa si una nueva línea se agrega al final de todo.txt, no los uses. Bueno, excepto el penúltimo. Eso no ensucia con el final.


59



No obtengo $ (...) ejecutado en absoluto. - SCL
Eso podría funcionar mejor (o nada) con comillas dobles en lugar de solo ... - ℝaphink
¿No será el -e también convertir secuencias de escape dentro de todo.txt? - mk12
Soluciones provisionales -> cat: <nombre de archivo de destino>: el archivo de entrada es el archivo de salida ... - ingyhere
printf sería mucho más consistente en todas las plataformas y, en general, debería funcionar más suavemente que echo -e - Peter Berg


los moreutils tener una buena herramienta llamada sponge:

echo "task goes here" | cat - todo.txt | sponge todo.txt

Va a "absorber" STDIN y luego escribir en el archivo, lo que significa que no tiene que preocuparse por los archivos temporales y moverlos.

Puedes obtener moreutils con muchas distribuciones de Linux, a través de apt-get install moreutils, o en OS X usando Homebrew, con brew install moreutils.


26





Puedes usar Vim en modo Ex:

ex -sc '1i|task goes here' -cx todo.txt
  1. 1 seleccionar primera línea

  2. i insertar

  3. x guardar y cerrar


5





Puede crear un nuevo archivo temporal.

echo "new task" > new_todo.txt
cat todo.txt >> new_todo.txt
rm todo.txt
mv new_todo.txt todo.txt

También puedes usar sed o awk. Pero básicamente sucede lo mismo.


3



Digamos que no tienes espacio en el disco para que new_todo.txt se escribe solo parcialmente Su solución parece perder el archivo original. - NPE
¿Quién se queda sin espacio en el disco? ;-) Es solo un simple ejemplo. - Keith
@Keith Alguien que trabaja en una VM que no esperaba necesitar una unidad virtual particularmente grande. O alguien moviendo un archivo grande. En cualquier caso, el argumento real en contra de esto es permisos de directorio; si no tiene permiso para crear nuevos archivos en el directorio dado, el único comando que se ejecutará correctamente en su secuencia de comandos es el rm del archivo original. - Parthian Shot


Si el archivo de texto es lo suficientemente pequeño como para caber en la memoria, no tiene que crear un archivo temporal para reemplazarlo. Puede cargarlo todo en la memoria y volver a escribirlo en el archivo.

echo "$(echo 'task goes here' | cat - todo.txt)" > todo.txt

Es imposible agregar líneas al principio del archivo sin sobre escribir el archivo completo.


3



Solo para hacer la pregunta obvia: ¿Dónde está el límite de caracteres de las variables de shell? - nixda
Por lo que yo sé, solo está limitado por la cantidad de memoria disponible. He llenado variables de más de 100MB en memoria. text=$(cat file). Sin embargo, tenga cuidado de solo usar texto, ya que las variables de shell no son binarias. mywiki.wooledge.org/BashFAQ/058 - Rucent88


No puede insertar contenido al principio de un archivo. Lo único que puede hacer es reemplazar el contenido existente o anexar bytes después del final del archivo actual.

Cualquier solución a su pregunta requiere un archivo temporal (o buffer) para ser creado (en la memoria o en el disco) que finalmente sobrescribirá el archivo original.

Tenga cuidado de no perder datos conservando el archivo original mientras crea el nuevo, en caso de que el sistema de archivos esté lleno durante el proceso. p.ej:

cat <(echo task go there) todo.txt > todo.txt.new && mv todo.txt.new todo.txt

2



Downvoters son bienvenidos para explicar su motivación. Ninguna de las respuestas restantes, incluida la aceptada, contradice nada en mi respuesta. - jlliagre
Esto es difícil de analizar ya que los <...> parecen corchetes, lo que supongo que no es así. Un espacio entre el <y el (¿podría ayudar? - dumbledad
Esto no funciona para mí echo HOME=\"/g/Users/timregan/\" | cat - 'F:\Program Files\Git\etc\profile' funciona pero cat <echo HOME=\"/g/Users/timregan/\" 'F:\Program Files\Git\etc\profile' da el error "echo: No hay tal archivo o directorio" - dumbledad
@dumbledad Estás pensando demasiado mi respuesta. No hay nada que puedas analizar en él. Un espacio entre el < y el ( rompería la sintaxis. Tratar cat <(echo HOME=\"/g/Users/timregan/\") 'F:\Program Files\Git\etc\profile' - jlliagre


Puedes usar tee:

echo 'task goes here' | cat - todo.txt | tee todo.txt

1



No, no puedes askubuntu.com/a/752451 - Steven Penny


GitBash + Windows10 + Multilínea:

Aquí hay una versión que te permite usar cadenas de varias líneas.

##############################################
## This section for demo purpose only,      ##
## So you can save entire file as           ##
## whatever.sh and run it.                  ##
##                                          ##
##############################################
> MY_TARGET_FILE.txt ##Make Or Clear File
echo "[STARTER_CONTENT]" >> MY_TARGET_FILE.txt
##############################################

## Below is main code:

##################################################
TARGET_FILE_VARIABLE="MY_TARGET_FILE.txt"
ADD_TO_HEAD_VARIABLE=$(cat << "HEREDOC_HEAD_TEXT"
//|  +-------------------------------------+   |//
//|  |                                     |   |//
//|  |     MESSAGE_FOR_HEAD_OF_FILE        |   |//
//|  |                                     |   |//
//|  +-------------------------------------+   |//
HEREDOC_HEAD_TEXT
)
##################################################
TAR=$TARGET_FILE_VARIABLE                       ##
TEX=$ADD_TO_HEAD_VARIABLE                       ##
echo "$TEX" | cat - $TAR > TEMP && mv TEMP $TAR ##
##################################################

## Expected contents of MY_TARGET_FILE.txt :
## //|  +-------------------------------------+   |//
## //|  |                                     |   |//
## //|  |     MESSAGE_FOR_HEAD_OF_FILE        |   |//
## //|  |                                     |   |//
## //|  +-------------------------------------+   |//
## [STARTER_CONTENT]

0