Perché questo non funziona? “Ls * .txt | xargs cat> all.txt ”(tutti i file in un singolo documento txt)


20

Perché questo non funziona?

ls *.txt | xargs cat > all.txt

(Voglio unire il contenuto di tutti i file di testo in un unico file 'all.txt'). Trovare anche con -exec dovrebbe funzionare, ma mi piacerebbe davvero capire la sintassi di xargs.

Grazie


1
Anche se non usare lsper questo . Se davvero non puoi usarlo, cat *.txt >all.txtprova printf '%s\0' *.txt | xargs -r0 cat >alle poi mv all all.txtper evitare che il file faccia riferimento a se stesso.
Tripleee

Risposte:


27

ls *.txt | xargs cat >> all.txt

potrebbe funzionare un po 'meglio, poiché si aggiungerebbe a all.txt invece di crearlo nuovamente dopo ogni file.

A proposito, cat *.txt >all.txtfunzionerebbe anche. :-)


6
Il gatto * .txt> all.txt è naturalmente migliore. Grazie
ajo

1
Tuttavia, il ... | xargs cat >> all.txt o> all.txt restituiscono sempre errori con xargs: virgoletta singola senza pari ... È perché xargs prende tutto dopo di esso come comando?
ajo

1
Hai nomi di file con spazi? Se è così, usa qualcosa come "find / your / path -iname '* .txt' -print0 | xargs -0 cat >> all.txt" invece
Janne Pikkarainen,

1
no, ho sostituito tutti gli spazi del nome file con . Ma a pensarci bene, è probabile che alcuni nomi di file includano virgolette singole come in listing_O'Connor .txt, questo potrebbe essere il problema!
ajo

Sì, questo è il problema allora. :) Il modo più semplice e più sano è usare find con -print0 combinato con xargs -0 - quindi l'intera catena userà il carattere NULL come separatore e gli spazi bianchi e i caratteri speciali verranno curati automaticamente.
Janne Pikkarainen,

3

Se alcuni dei nomi dei tuoi file contengono "," o lo spazio xargsnon riuscirà a causa del problema del separatore

In generale, non correre mai xargssenza -0 poiché tornerà e ti morderà un giorno.

Prendi invece in considerazione l'utilizzo di GNU Parallel:

ls *.txt | parallel cat > tmp/all.txt

o se preferisci:

ls *.txt | parallel cat >> tmp/all.txt

Ulteriori informazioni su GNU Parallel http://www.youtube.com/watch?v=OpaiGYxkSuQ


1

all.txt è un file nella stessa directory, quindi cat si confonde quando vuole scrivere dallo stesso file nello stesso file.

D'altro canto:

ls *.txt | xargs cat > tmp/all.txt

Questo leggerà dai file di testo nella directory corrente in all.txt in una sottodirectory (non inclusa con *.txt).


Ancora il seguente errore: xargs: virgoletta singola senza eguali; per impostazione predefinita le virgolette sono speciali per xargs a meno che tu non usi l'opzione -0
ajo

1
Hai un file .txt con una sola virgoletta nel suo nome?
Jeremy Smyth,

0

Potresti anche imbatterti in una limitazione della lunghezza della riga di comando. Parte del motivo dell'uso xargsè che suddivide l'input in blocchi sicuri delle dimensioni di una riga di comando. Quindi, immagina una situazione in cui hai centinaia di migliaia di file .txt nella directory. ls *.txtavrà esito negativo. Dovresti fare

ls | grep .txt$ |xargs cat > /some/other/path/all.txt

.txt$in questo caso è un'espressione regolare che corrisponde a tutto ciò che termina in .txt (quindi non è esattamente come *.txt, poiché se si dispone di un file chiamato atxt, allora *.txtnon corrisponderebbe, ma l'espressione regolare lo farebbe.)

L'uso di un altro percorso è perché, come hanno sottolineato altre risposte, all.txt è associato al modello, *.txtquindi ci sarebbe un conflitto tra input e output.

Nota che se hai dei file con i 'loro nomi (e questa potrebbe essere la causa unmatched single quotedell'errore), dovresti farlo

ls | grep --null .txt$ | xargs -0 cat > /some/other/path/all.txt

L'opzione --null dice a grep di usare l'output separato da un carattere \0(aka null) invece della newline predefinita, e l' -0opzione `xargs dice che si aspetta che il suo input sia nello stesso formato. Funzionerebbe anche se avessi nomi di file con newline in essi.

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.