Come aggiungere un file a un altro in Linux dalla shell?


418

Ho due file: file1e file2. Come faccio ad aggiungere i contenuti di file2in file1modo che i contenuti di file1persistano nel processo?

Risposte:


611

Usa il reindirizzamento incorporato bash (tldp) :

cat file2 >> file1

2
In che modo il file di destinazione non è di tua proprietà e devi utilizzare sudo?
Bijay Rungta,

1
@BijayRungta: Sembra che tu abbia risposto alla tua domanda. Dovresti precedere sudoil catcomando (e inserire le credenziali se richiesto).
David,

devi ... chmod 777 / etc / default / docker per darti i permessi di scrittura su quel file - assicurati di ripristinare i vecchi permessi dei file una volta fatto
danday74

1
@Sigur: A meno che non ci sia un modo per indirizzare l'output su due file contemporaneamente, ciò implicherebbe due invocazioni del comando.
David,

2
@Sigur o dare un'occhiata al teeprogramma: cat 1 | tee -a 2 3. Puoi inserire tutti i file che desideri dopo l'opzione --append(o -ain breve).
Stefan van den Akker,

291

cat file2 >> file1

L' >>operatore aggiunge l'output al file indicato o crea il file indicato se non esiste.

cat file1 file2 > file3

Ciò concatena due o più file a uno. Puoi avere tutti i file sorgente di cui hai bisogno. Per esempio,

cat *.txt >> newfile.txt

Aggiornamento 20130902
Nei commenti eumiro suggerisce "non provare cat file1 file2 > file1". Il motivo per cui ciò potrebbe non comportare il risultato previsto è che il file che riceve il reindirizzamento viene preparato prima dell'esecuzione del comando a sinistra di >. In questo caso, prima file1viene troncato a zero e aperto per l'output, quindi il catcomando tenta di concatenare il file ora a lunghezza zero più il contenuto di file2into file1. Il risultato è che il contenuto originale di file1viene perso e al suo posto è una copia del file2quale probabilmente non è quello che ci si aspettava.

Aggiornamento 20160919
Nei commenti tpartee suggerisce di collegarsi a informazioni / fonti di supporto. Per un riferimento autorevole, indirizzo il gentile lettore alla pagina di manuale di linuxcommand.org che afferma:

Prima dell'esecuzione di un comando, l'input e l'output possono essere reindirizzati utilizzando una notazione speciale interpretata dalla shell.

Mentre questo dice al lettore cosa devono sapere, è facile perdere se non lo stai cercando e analizzando la frase parola per parola. La parola più importante qui è "prima". Il reindirizzamento è completato (o non riesce) prima dell'esecuzione del comando.

Nel caso di esempio della cat file1 file2 > file1shell esegue prima il reindirizzamento in modo che gli handle di I / O siano presenti nell'ambiente in cui verrà eseguito il comando prima che venga eseguito.

Una versione più amichevole in cui la precedenza sul reindirizzamento è ampiamente trattata può essere trovata sul sito web di Ian Allen sotto forma di corsi Linux. La sua pagina Note di reindirizzamento I / O ha molto da dire sull'argomento, inclusa l'osservazione che il reindirizzamento funziona anche senza un comando. Passando questo alla shell:

$ >out

... crea un file vuoto chiamato. La shell prima imposta il reindirizzamento I / O, quindi cerca un comando, non ne trova nessuno e completa l'operazione.


17
@asir - non provarci cat file1 file2 > file1- questo non funzionerà come probabilmente stai aspettando.
eumiro,

5
In realtà questo è esattamente ciò di cui ha bisogno. Dice "senza sovrascrivere il file corrente1". I primi tre risponditori hanno completamente ignorato questa parte della domanda e suggerito un comando >>che usasse per modificare il file file1. T. Rob ha fatto un lavoro di gran lunga superiore nel spiegare la sua risposta piuttosto che correre semplicemente a presentare qualcosa che, in effetti, era errato. Sulla base del testo della domanda, credo che cat file1 file2 > file3sia il comando appropriato che @asir stava cercando.
dm78,

Grazie per le belle parole, David! Ciò che @eumiro sottolinea sopra ma non approfondisce è che l'operazione a destra di >viene eseguita per prima. Pertanto, l'esecuzione eseguirà cat file1 file2 > file1prima il clobber, file1quindi tenterà di copiare il file di lunghezza zero su se stesso. Ciò ha senso quando si pensa all'ordine in cui le operazioni potrebbero e dovrebbero verificarsi, ma è abbastanza sottile da sorprendere molte persone. Quindi, se non altro, eumiro e tu hai richiesto un ulteriore miglioramento della risposta. Grazie per quello!
T.Rob

Inoltre , non provare cat file1 >> file1, questo causerà la riscrittura ricorsiva del file, lo faccio per errore e in pochi secondi, 50 milioni di righe sono state inserite nel file da appena qualche dozzina di righe.
Hendra Uzia,

Inoltre, solo per renderlo un po 'più conciso, se il "nuovo file" esiste già, >> accoda il file e lo > sostituisce .
Rinogo,

43

Nota : se è necessario utilizzare sudo , procedere come segue:

sudo bash -c 'cat file2 >> file1'

Il solito metodo di anteporre semplicemente sudoal comando fallirà, poiché l'escalation dei privilegi non viene trasferita nel reindirizzamento dell'output.


6
Un altro linguaggio comune per questo ècat file2 | sudo tee -a file1 > /dev/null
ianw


13

Solo per riferimento, l'uso di ddrescue fornisce un modo interrompibile per raggiungere l'attività se, ad esempio, si dispone di file di grandi dimensioni e la necessità di sospendere e proseguire in un secondo momento:

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

Questa logfileè la parte importante. È possibile interrompere il processo Ctrl-Ce riprenderlo specificando nuovamente lo stesso comando esatto e ddrescue leggerà logfilee riprenderà da dove era stato interrotto. Il -o Aflag indica a ddrescue di iniziare dal byte A nel file di output ( file1). Quindi wc --bytes file1 | awk '{ print $1 }'estrae solo la dimensione file1in byte (puoi semplicemente incollare l'output lsse vuoi).

Come sottolineato da ngks nei commenti, il rovescio della medaglia è che ddrescue probabilmente non verrà installato di default, quindi dovrai installarlo manualmente. L'altra complicazione è che ci sono due versioni di ddrescue che potrebbero essere nei tuoi repository: vedi questa domanda di askubuntu per maggiori informazioni. La versione che vuoi è GNU ddrescue, e sui sistemi basati su Debian è il pacchetto chiamato gddrescue:

sudo apt install gddrescue

Per altre distro, controlla il tuo sistema di gestione dei pacchetti per la versione GNU di ddrescue.


1
A beneficio dei nuovi utenti: ddrescue è uno strumento GNU, ma potrebbe non esistere su Linux, Mac o altri sistemi unix-like. ddrescue non sembra essere richiesto da POSIX o da qualsiasi altro standard.

2

Un'altra soluzione:

cat file1 | tee -a file2

tee ha il vantaggio che puoi aggiungere a tutti i file che desideri, ad esempio:

cat file1 | tee -a file2 file3 file3

aggiungerà il contenuto di file1a file2, file3e file4.

Dalla pagina man:

-a, --append
       append to the given FILEs, do not overwrite

0

catpuò essere la soluzione semplice ma che diventa molto lenta quando concatichiamo file di grandi dimensioni, find -printè salvarti, anche se devi usare cat una volta.

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

Il risparmio di tempo segnalato per il comando combo find / cat è dovuto al fatto che stai programmando solo il comando find che stampa i nomi dei file. Prova a cronometrare l'intero comando in questo modo: time (find . -maxdepth 1 -type f -name 'bigFile*' -print0 | xargs -0 cat -- > outFile1)e dovrebbe produrre risultati simili al comando solo del tuo gatto.
JoshMc

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.