¿Cómo insertar un texto al comienzo de un archivo?

213

Hasta ahora he podido encontrar cómo agregar una línea al comienzo de un archivo, pero eso no es exactamente lo que quiero. Lo mostraré en un ejemplo.

Contenido del archivo

some text at the beginning

Resultado

<added text> some text at the beginning

Es similar pero no quiero crear ninguna nueva línea con él ...

Me gustaría hacer esto sedsi es posible.

usuario219882
fuente
¿Algo aquí funciona para ti? stackoverflow.com/questions/54365/… - no necesita usar sed.
wkl

Respuestas:

314

sed puede operar en una dirección:

$ sed -i '1s/^/<added text> /' file

¿Qué es este mágico 1sque ves en cada respuesta aquí? Direccionamiento de línea! .

¿Quieres agregar <added text>en las primeras 10 líneas?

$ sed -i '1,10s/^/<added text> /' file

O puedes usar Command Grouping:

$ { echo -n '<added text> '; cat file; } >file.new
$ mv file{.new,}
kev
fuente
67
Para insertar realmente una nueva línea: sed -i '1s / ^ / <texto agregado> \ n /' archivo
jslatts
1
¿Por qué usar -i ?? Sobre el hombre dice que es por sufijo. linux.die.net/man/1/sed
endrigoantonini
-i significa in situ, puede agregar un sufijo a -i para hacer una copia en lugar de sobrescribirla. -i.new crearía un nuevo archivo que terminara con .new, pero solo -i editaría el archivo directamente.
Jay Kamat
3
Tenga en cuenta que el sed no funcionará en un archivo vacío: no se puede hacer que un sed falso haga nada con la entrada de longitud 0.
Jthill
2
El defecto de esta solución es que no agrega el texto si el archivo está vacío.
DBedrenko
41

Si desea agregar una línea al comienzo de un archivo, debe agregar \nal final de la cadena en la mejor solución anterior.

La mejor solución agregará la cadena, pero con la cadena, no agregará una línea al final de un archivo.

sed -i '1s/^/your text\n/' file
Ali Reza Ebadat
fuente
27

Si el archivo es solo una línea, puede usar:

sed 's/^/insert this /' oldfile > newfile

Si es más de una línea. uno de:

sed '1s/^/insert this /' oldfile > newfile
sed '1,1s/^/insert this /' oldfile > newfile

He incluido este último para que sepa cómo hacer rangos de líneas. Ambos "reemplazan" el marcador de la línea de inicio en sus líneas afectadas con el texto que desea insertar. También puedes (suponiendo que tu sedes lo suficientemente moderno) usar:

sed -i 'whatever command you choose' filename

para hacer la edición en el lugar.

paxdiablo
fuente
11

Puedes usar cat -

printf '%s' "some text at the beginning" | cat - filename
Lex
fuente
66
Esto solo generará el texto seguido del contenido del archivo, pero no modifica el archivo en absoluto.
Adaephon
Esa es una buena solución, me pregunto por qué no recibió ningún voto positivo. Aquí está el mío, mi buen señor. Además, ¿por qué printf y no un simple eco?
ychaouche
1
@ychaouche: ¿presumiblemente porque no hay una forma portátil de evitar echoagregar una nueva línea?
Toby Speight
He intentado dirigir esto en un archivo añadiendo > fileal comando, se jus correo basura mi terminal con"some text at the beginning"
theonlygusti
2
printf '%s' "some text" | cat - filename > tmpfile && mv tmpfile filename
luca
11

Para insertar solo una nueva línea:

sed '1i\\'

fuente
Me pregunto por qué las respuestas más votadas usan todos s en lugar de i. ¿Alguna desventaja de esto?
César hace
8

Usar subshell:

echo "$(echo -n 'hello'; cat filename)" > filename
Nick Roz
fuente
5

Tenga en cuenta que en OS X sed -i <pattern> file, falla. Sin embargo, si proporciona una extensión de respaldo sed -i old <pattern> file, filese modifica en su lugar mientras file.oldse crea. Luego puede eliminar file.olden su secuencia de comandos.

Curt Clifton
fuente
44
O sed -i '' archivo. Luego solo editará en el lugar y no hará copias de seguridad.
Harv
He descubierto que macOS sed quiere editar un punto en su lugar sin crear una copia de seguridad: sed -i. Archivo <pattern>
Bryan el
4

PROBLEMA: etiquete un archivo, en la parte superior del archivo, con el nombre base del directorio principal.

Es decir, para

/mnt/Vancouver/Programming/file1

etiqueta la parte superior de file1con Programming.

SOLUCIÓN 1 - archivos no vacíos:

bn=${PWD##*/}    ## bn: basename

sed -i '1s/^/'"$bn"'\n/' <file>

1s coloca el texto en la línea 1 del archivo.

SOLUCIÓN 2 - archivos vacíos o no vacíos:

El sedcomando anterior falla en archivos vacíos. Aquí hay una solución, basada en /superuser/246837/how-do-i-add-text-to-the-beginning-of-a-file-in-bash/246841#246841

printf "${PWD##*/}\n" | cat - <file> > temp && mv -f temp <file>

Tenga -en cuenta que se requiere el comando en el gato (lee la entrada estándar: consulte man catpara obtener más información). Aquí, creo, es necesario llevar la salida de la declaración printf (a STDIN), y poner eso y el archivo a temp ... Ver también la explicación al final de http://www.linfo.org/cat .html .

También agregué -fal mvcomando, para evitar que me pidan confirmaciones al sobrescribir archivos.

Para recurrir sobre un directorio:

for file in *; do printf "${PWD##*/}\n" | cat - $file > temp && mv -f temp $file; done

Tenga en cuenta también que esto se romperá sobre caminos con espacios; hay soluciones, en otros lugares (por ejemplo, solución de archivos o find . -type f ...soluciones de tipo) para esos.

APÉNDICE: Re: mi último comentario, este script le permitirá recurrir sobre directorios con espacios en las rutas:

#!/bin/bash

## /programming/4638874/how-to-loop-through-a-directory-recursively-to-delete-files-with-certain-extensi

## To allow spaces in filenames,
##   at the top of the script include: IFS=$'\n'; set -f
##   at the end of the script include: unset IFS; set +f

IFS=$'\n'; set -f

# ----------------------------------------------------------------------------
# SET PATHS:

IN="/mnt/Vancouver/Programming/data/claws-test/corpus test/"

# /superuser/716001/how-can-i-get-files-with-numeric-names-using-ls-command

# FILES=$(find $IN -type f -regex ".*/[0-9]*")        ## recursive; numeric filenames only
FILES=$(find $IN -type f -regex ".*/[0-9 ]*")         ## recursive; numeric filenames only (may include spaces)

# echo '$FILES:'                                      ## single-quoted, (literally) prints: $FILES:
# echo "$FILES"                                       ## double-quoted, prints path/, filename (one per line)

# ----------------------------------------------------------------------------
# MAIN LOOP:

for f in $FILES
do

  # Tag top of file with basename of current dir:
  printf "[top] Tag: ${PWD##*/}\n\n" | cat - $f > temp && mv -f temp $f

  # Tag bottom of file with basename of current dir:
  printf "\n[bottom] Tag: ${PWD##*/}\n" >> $f
done

unset IFS; set +f
Victoria Stuart
fuente
3

Hola con retorno de carro:

sed -i '1s/^/your text\n/' file
xck
fuente
3

Para agregar una línea en la parte superior del archivo:

sed -i '1iText to add\'
merienda
fuente
Esto incluye una nueva línea, que el interlocutor explícitamente no quiere.
Toby Speight
Gracias por darme exactamente lo que necesito
FindOutIslamNow
3

Hay una manera muy fácil:

echo "your header" > headerFile.txt
cat yourFile >> headerFile.txt
Raphael Villas Boas
fuente
Ow ... lo siento, ahora que me doy cuenta de que querías agregar al principio y no una nueva línea.
Raphael Villas Boas
Pero yo quería una nueva línea. Así que gracias por el enfoque simplista.
TheSatinKnight
3

Solo por diversión, aquí hay una solución edque no tiene el problema de no trabajar en un archivo vacío. Puede ponerlo en un script de shell como cualquier otra respuesta a esta pregunta.

ed Test <<EOF
a

.
0i
<added text>
.
1,+1 j
$ g/^$/d
wq
EOF

El script anterior agrega el texto para insertar en la primera línea y luego une la primera y la segunda línea. Para evitar que Ed salga por error con una unión no válida, primero crea una línea en blanco al final del archivo y la elimina más tarde si aún existe.

Limitaciones: este script no funciona si <added text>es exactamente igual a un único período.

merlin2011
fuente
2

Mis dos centavos:

sed  -i '1i /path/of/file.sh' filename

Esto funcionará incluso si la cadena contiene barra diagonal "/"

vardhan
fuente
1
echo -n "text to insert " ;tac filename.txt| tac > newfilename.txt

El primero taccanaliza el archivo hacia atrás (última línea primero) para que el "texto a insertar" aparezca en último lugar. El segundo lo tacenvuelve una vez más, por lo que la línea insertada está al principio y el archivo original está en su orden original.

paulp
fuente
1
¿Puede explicar cómo esto ayudaría a Tomas con el problema?
John Odom
tac | tac: así es como se forman las mentalidades no escalables :-(
Michael Shigorin
0

Otra solución con alias. Agregue a su archivo init rc / env:

addtail () { find . -type f ! -path "./.git/*" -exec sh -c "echo $@ >> {}" \; }
addhead () { find . -type f ! -path "./.git/*" -exec sh -c  "sed -i '1s/^/$@\n/' {}" \; }

Uso:

addtail "string to add at the beginning of file"
addtail "string to add at the end of file"
0x8BADF00D
fuente