¿Cómo agrego texto al principio y al final de varios archivos de texto en Bash?

24

Tengo un directorio lleno de archivos de texto. Mi objetivo es agregar texto al principio y al final de todos ellos. El texto que va al principio y al final es el mismo para cada archivo.

Basado en el código que obtuve de la web, este es el código para agregar al comienzo del archivo:

echo -e 'var language = {\n$(cat $BASEDIR/Translations/Javascript/*.txt)' > $BASEDIR/Translations/Javascript/*.txt

Este es el código para agregar al final del archivo. El objetivo es agregar el texto };al final de cada archivo:

echo "};" >> $BASEDIR/Translations/Javascript/*.txt

Los ejemplos que extraje fueron para actuar en archivos individuales. Pensé que iba a tratar actuando en varios archivos usando el comodín, *.txt.

Podría estar cometiendo otros errores también. En cualquier caso, ¿cómo agrego texto al principio y al final de varios archivos?

Preguntador
fuente

Respuestas:

27

Para anteponer texto a un archivo que puede usar (con la implementación GNU de sed):

sed -i '1i some string' file

Añadir texto es tan simple como

echo 'Some other string' >> file

Lo último que debe hacer es poner eso en un bucle que itera sobre todos los archivos que tiene la intención de editar:

for file in *.txt; do
  sed -i '1i Some string' "$file" &&
  echo 'Some other string' >> "$file"
done
Marco
fuente
8

Puedes usar GNU sed

Como ya se ilustra, puede insertar líneas de texto justo antes y después de hacer coincidir las líneas de un archivo con sedel comando iy arespectivamente. Lo que no se ha demostrado es que puede hacerlo con una sola línea y para múltiples archivos a la vez.

Lo siguiente insertará una línea antes de la primera 1iy después de la última línea $a. Las inserciones se ejecutarán para todos los archivos que coincidan con el glob *.txt.

sed -i -e '1ivar language = {' -e '$a};' -- *.txt

Ambos iy ano solo funcionan con números de línea, sino también en cada línea que coincide con un patrón dado. Esto insertaría un comentario cada vez que una línea contenga var y = 2;:

sed -i -- '/var y = 2;/i//initialize variable y' *.js
J. Katzwinkel
fuente
5

Comando totalmente compatible con POSIX, utilizando ex:

for f in *.txt; do printf '%s\n' 0a 'var language = {' . '$a' '};' . x | ex "$f"; done

Si ejecuta la printfparte del comando por sí mismo, verá los comandos de edición exactos que está pasando a ex:

0a
var language = {
.
$a
};
.
x

0asignifica "Agregar texto después de la línea 0" (en otras palabras, antes de la primera línea). La siguiente línea es el texto literal para "agregar" después de la línea 0. El punto ( .) en una línea por sí solo finaliza el texto que se va a agregar.

$a significa agregar texto después de la última línea del archivo.

x significa guardar los cambios y salir.

Comodín
fuente
2

Aquí hay una manera de hacerlo en Perl:

for f in ./*txt; do
  perl -lpe 'BEGIN{print "First string"}END{print "Last string"}' "$f" > foo && 
  mv foo "$f";
done
terdon
fuente
@ StéphaneChazelas agregar en -ilugar de esta sustitución de archivos no funciona, solo se imprime en stdout.
Oleh Prypin
@OlehPrypin, de hecho, tienes razón. Comentario borrado.
Stéphane Chazelas
1

Intenta usar ex:

ex -s +'bufdo!1s/^/HEAD/|$s/$/TAIL/' -cxa *.foo

donde los comandos son:

  • bufdo!ejecuta los siguientes comandos para cada búfer / archivo abierto (nota: no es POSIX )
  • 1s/^/HEAD/- inserta HEADtexto en la primera línea al comienzo de la línea
  • $s/$/TAIL/- agrega TAILtexto en la última línea al final de la línea

y los argumentos son:

  • -s - modo silencioso / rápido
  • -cxa - guardar todos los búferes / archivos abiertos y salir
  • *.foo- todos los archivos en el directorio actual ( *) con foola extensión, el uso **/*.foode la recursividad (después de permitir Globstar: shopt -s globstar)
kenorb
fuente
1
note que bufdo no es POSIX pubs.opengroup.org/onlinepubs/9699919799/utilities/ex.html
Steven Penny
1
@StevenPenny tiene razón. Yo uso las características específicas de POSIX solo, personalmente, para las ediciones con script.
Comodín el
1

Con gnu awk, usando la inplaceextensión y BEGINFILE/ ENDFILE:

gawk -i inplace 'BEGINFILE{print "INSERT"};ENDFILE{print "APPEND"};1' ./*.txt
don_crissti
fuente
1

También tiene derecho a ser (con resultados en .outarchivos):

find . -name '*.txt' -exec sh -c '(echo HEAD;cat {};echo FOOT) > {}.out' \;

Otra variante más elaborada: los archivos fuente se reemplazan por el resultado:

find . -name '*.txt' -exec sh -c '(echo HEAD;cat {};echo FOOT) > {}.tmp && mv {}.tmp {}' \; -print
torre
fuente
0

Perl one-liner al rescate:

perl -i -pe'$_="FIRST LINE\n$_"if$.<2;$.=0,$_.="LAST LINE\n"if eof' *.txt
Kjetil S.
fuente