Por que isso não funciona? "Ls * .txt | xargs cat> all.txt "(todos os arquivos em um único documento txt)

20

Por que isso não funciona?

ls *.txt | xargs cat > all.txt

(Quero juntar o conteúdo de todos os arquivos de texto em um único arquivo 'all.txt'.) O achado com -exec também deve funcionar, mas eu realmente gostaria de entender a sintaxe do xargs.

obrigado

ajo
fonte
11
Embora não use lspara isso . Se você realmente não pode usar cat *.txt >all.txt, em seguida, tentar printf '%s\0' *.txt | xargs -r0 cat >alle, em seguida, mv all all.txtpara evitar que o arquivo de referência em si.
tripleee 24/07

Respostas:

27

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

pode funcionar um pouco melhor, pois seria anexado a all.txt em vez de criá-lo novamente após cada arquivo.

By the way, cat *.txt >all.txttambém funcionaria. :-)

Janne Pikkarainen
fonte
6
O gato * .txt> all.txt é naturalmente melhor. Obrigado
ajo
11
No entanto, o ... | xargs cat >> all.txt ou> all.txt sempre retornam erro com xargs: aspas simples incomparáveis ​​... É porque o xargs leva tudo depois como comando?
ajo
11
Você tem nomes de arquivos com espaços? Nesse caso, use algo como "find / your / path -iname '* .txt' -print0 | xargs -0 cat >> all.txt" em vez disso
Janne Pikkarainen
11
não, substituí todos os espaços de nome de arquivo por . Mas, pensando bem, é provável que alguns nomes de arquivos incluam aspas simples, como em Listing_O'Connor .txt, este pode ser o problema!
ajo
Sim, esse é o problema então. :) A maneira mais fácil e mais segura é usar find com -print0 combinado com xargs -0 - então toda a cadeia usará o caractere NULL como separador e os espaços em branco e os caracteres especiais serão resolvidos automaticamente.
Janne Pikkarainen
3

Se alguns dos nomes de arquivos contiverem ', "ou o espaço xargsfalhará devido ao problema do separador

Em geral, nunca corra xargssem -0, pois ele voltará e o morderá um dia.

Considere usar o GNU Parallel:

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

ou se você preferir:

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

Saiba mais sobre o GNU Parallel http://www.youtube.com/watch?v=OpaiGYxkSuQ

Ole Tange
fonte
1

all.txt é um arquivo no mesmo diretório; portanto, o gato fica confuso quando deseja gravar do mesmo arquivo no mesmo arquivo.

Por outro lado:

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

Isso lerá de arquivos de texto no seu diretório atual para o all.txt em um subdiretório (não incluído no *.txt).

Jeremy Smyth
fonte
Ainda o seguinte erro: xargs: aspas simples incomparáveis; por aspas padrão são especiais para xargs menos que você use a opção -0
ajo
11
Você tem um arquivo .txt com uma única citação no nome?
Jeremy Smyth
0

Você também pode encontrar uma limitação de comprimento de linha de comando. Parte do motivo do uso xargsé que ele divide a entrada em blocos seguros do tamanho da linha de comando. Então, imagine uma situação em que você tenha centenas de milhares de arquivos .txt no diretório. ls *.txtvai falhar. Você precisaria fazer

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

.txt$nesse caso, é uma expressão regular que corresponde a tudo que termina em .txt (portanto, não é exatamente como *.txt, pois se você tiver um arquivo chamado atxt, *.txtele não corresponderia, mas a expressão regular seria).

O uso de outro caminho é porque, como outras respostas apontaram, all.txt é correspondido pelo padrão, *.txtportanto, haveria um conflito entre entrada e saída.

Observe que, se você tiver algum arquivo com 'seus nomes (e isso pode ser a causa do unmatched single quoteerro), convém fazer isso

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

A opção --null diz ao grep para usar a saída separada por um caractere \0(nulo) em vez da nova linha padrão, e a -0opção `xargs diz para esperar sua entrada no mesmo formato. Isso funcionaria mesmo se você tivesse nomes de arquivos com novas linhas.

Brian Minton
fonte