¿Cómo agregar un archivo a otro en Linux desde el shell?

418

Tengo dos archivos: file1y file2. ¿Cómo agrego los contenidos de file2a file1para que los contenidos de file1persistan en el proceso?

asir
fuente

Respuestas:

611

Utilice la redirección integrada de bash (tldp) :

cat file2 >> file1
David
fuente
2
¿Cómo lo haces? ¿El archivo de destino no te pertenece y necesitas usar sudo?
Bijay Rungta
1
@BijayRungta: Parece que respondiste tu propia pregunta. Debería preceder sudoal catcomando (e ingresar las credenciales si se le solicita).
David
necesita ... chmod 777 / etc / default / docker para otorgarse permisos de escritura en ese archivo - asegúrese de restaurar los permisos de archivo antiguos una vez hecho
danday74
1
@Sigur: a menos que haya una manera de dirigir la salida a dos archivos a la vez, implicaría dos invocaciones del comando.
David
2
@Sigur o echar un vistazo a la teeprograma: cat 1 | tee -a 2 3. Puede colocar tantos archivos como desee después del interruptor --append(o -apara abreviar).
Stefan van den Akker
291

cat file2 >> file1

El >>operador agrega la salida al archivo con nombre o crea el archivo con nombre si no existe.

cat file1 file2 > file3

Esto concatena dos o más archivos a uno. Puede tener tantos archivos fuente como necesite. Por ejemplo,

cat *.txt >> newfile.txt

Actualización 20130902
En los comentarios, eumiro sugiere "no intentes cat file1 file2 > file1". La razón por la que esto podría no dar como resultado el resultado esperado es que el archivo que recibe la redirección se prepara antes de que >se ejecute el comando a la izquierda del . En este caso, primero file1se trunca a longitud cero y se abre para la salida, luego el catcomando intenta concatenar el archivo ahora de longitud cero más el contenido de file2into file1. El resultado es que el contenido original de file1se pierde y en su lugar hay una copia de la file2cual probablemente no es lo que se esperaba.

Actualización 20160919
En los comentarios, tpartee sugiere vincular a fuentes / información de respaldo. Para una referencia autorizada, dirijo al amable lector a la página de manual en linuxcommand.org que dice:

Antes de ejecutar un comando, su entrada y salida pueden redirigirse utilizando una notación especial interpretada por el shell.

Si bien eso le dice al lector lo que necesita saber, es fácil pasarlo por alto si no lo está buscando y analizando la declaración palabra por palabra. La palabra más importante aquí es 'antes'. La redirección se completa (o falla) antes de ejecutar el comando.

En el caso de ejemplo de cat file1 file2 > file1 el shell realiza la redirección primero para que los identificadores de E / S estén en su lugar en el entorno en el que se ejecutará el comando antes de ejecutarse.

En el sitio web de Ian Allen, en forma de software para cursos de Linux, se puede encontrar una versión más amigable en la que se cubre la precedencia de la redirección. Su página de Notas de redirección de E / S tiene mucho que decir sobre el tema, incluida la observación de que la redirección funciona incluso sin un comando. Pasando esto al shell:

$ >out

... crea un archivo vacío con nombre. El shell primero configura la redirección de E / S, luego busca un comando, no encuentra ninguno y completa la operación.

T.Rob
fuente
17
@asir, no lo intentes cat file1 file2 > file1, esto no funcionará como probablemente estés esperando.
eumiro
55
En realidad esto es exactamente lo que necesita. Él dice "sin sobrescribir el archivo actual1". Los tres primeros que responden han hecho caso omiso de esta parte de la cuestión y sugirió un comando con >>el que va a modificar el archivo file1. T.Rob hizo un trabajo muy superior al explicar su respuesta en lugar de simplemente correr para presentar algo que, de hecho, era incorrecto. Basado en el texto de la pregunta, creo que ese cat file1 file2 > file3es el comando apropiado que @asir estaba buscando.
dm78
Gracias por las amables palabras, David! Lo que @eumiro señala arriba pero no entra en detalles es que la operación a la derecha de la >se ejecuta primero. Entonces, la ejecución cat file1 file2 > file1primero file1intentaría luego copiar el archivo de longitud cero en sí mismo. Esto tiene sentido cuando piensa en el orden en que las operaciones podrían y deberían ocurrir, pero es lo suficientemente sutil como para sorprender a muchas personas. Entonces, si nada más, eumiro y usted han impulsado una mejora adicional a la respuesta. ¡Gracias por eso!
T.Rob
Además , no intente cat file1 >> file1, esto hará que el archivo se reescriba recursivamente, lo hago por error y en solo unos segundos, se han colocado 50 millones de líneas en el archivo de unas pocas docenas de líneas.
Hendra Uzia
Además, solo para hacerlo un poco más conciso, si el "nuevo archivo" ya existe, se >> agrega al archivo y lo > reemplaza .
rinogo
43

Nota : si necesita usar sudo , haga esto:

sudo bash -c 'cat file2 >> file1'

El método habitual de simplemente anteponer sudoel comando fallará, ya que la escalada de privilegios no se transfiere a la redirección de salida.

jdunk
fuente
66
Otro idioma común para esto escat file2 | sudo tee -a file1 > /dev/null
ianw
28

Prueba este comando:

cat file2 >> file1
eumiro
fuente
13

Solo como referencia, el uso de ddrescue proporciona una forma interrumpible de lograr la tarea si, por ejemplo, tiene archivos grandes y la necesidad de pausar y luego continuar en algún momento posterior:

ddrescue -o $(wc --bytes file1 | awk '{ print $1 }') file2 file1 logfile

El logfilees el bit importante. Puede interrumpir el proceso Ctrl-Cy reanudarlo especificando exactamente el mismo comando nuevamente y ddrescue leerá logfiley reanudará desde donde lo dejó. La -o Abandera le dice a ddrescue que comience desde el byte A en el archivo de salida ( file1). Entonces wc --bytes file1 | awk '{ print $1 }'solo extrae el tamaño file1en bytes (puede pegar en la salida dels si lo desea).

Como señalaron los ngks en los comentarios, la desventaja es que ddrescue probablemente no se instalará de manera predeterminada, por lo que deberá instalarlo manualmente. La otra complicación es que hay dos versiones de ddrescue que pueden estar en sus repositorios: consulte esta pregunta de askubuntu para obtener más información. La versión que desea es el ddrescue de GNU, y en los sistemas basados ​​en Debian es el paquete llamado gddrescue:

sudo apt install gddrescue

Para otras distribuciones, verifique su sistema de administración de paquetes para la versión GNU de ddrescue.

Zorawar
fuente
1
Para el beneficio de los nuevos usuarios: ddrescue es una herramienta GNU, pero puede no existir en su sistema Linux, Mac u otro sistema similar a Unix. ddrescue no parece ser requerido por POSIX o cualquier otro estándar.
2

Otra solución:

cat file1 | tee -a file2

tee tiene la ventaja de que puede agregar tantos archivos como desee, por ejemplo:

cat file1 | tee -a file2 file3 file3

agregará los contenidos de file1a file2, file3y file4.

Desde la página del manual:

-a, --append
       append to the given FILEs, do not overwrite
Stefan van den Akker
fuente
0

catpuede ser la solución fácil, pero eso se vuelve muy lento cuando capturamos archivos grandes, find -printes rescatarlo, aunque debe usar cat una vez.

amey@xps ~/work/python/tmp $ ls -lhtr
total 969M
-rw-r--r-- 1 amey amey 485M May 24 23:54 bigFile2.txt
-rw-r--r-- 1 amey amey 485M May 24 23:55 bigFile1.txt

 amey@xps ~/work/python/tmp $ time cat bigFile1.txt bigFile2.txt >> out.txt

real    0m3.084s
user    0m0.012s
sys     0m2.308s


amey@xps ~/work/python/tmp $ time find . -maxdepth 1 -type f -name 'bigFile*' -print0 | xargs -0 cat -- > outFile1

real    0m2.516s
user    0m0.028s
sys     0m2.204s
Amey Jadiye
fuente
El ahorro de tiempo que informa para su comando combo find / cat se debe a que solo está cronometrando el comando find que está imprimiendo los nombres de los archivos. Intente cronometrar todo el comando de esta manera: time (find . -maxdepth 1 -type f -name 'bigFile*' -print0 | xargs -0 cat -- > outFile1)y debería producir resultados similares al comando de solo gato.
JoshMc
0

También puede hacerlo sin cat, aunque honestamente cates más legible:

>> file1 < file2

El >>anexa STDIN a file1y la <vuelca file2a STDIN .

Alok Singh
fuente
1
No funciona
user202729
@ user202729 Tienes razón, no funciona en bash. Funciona en zsh.
Alok Singh