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.