Como anexar conteúdo de vários arquivos em um arquivo


173

Quero copiar o conteúdo de cinco arquivos para um arquivo como está. Eu tentei fazê-lo usando cp para cada arquivo. Mas isso substitui o conteúdo copiado do arquivo anterior. Eu também tentei

paste -d "\n" 1.txt 0.txt

e não funcionou.

Quero que meu script adicione a nova linha no final de cada arquivo de texto.

por exemplo. Arquivos 1.txt, 2.txt, 3.txt. Coloque conteúdo de 1,2,3 em 0.txt

Como eu faço isso ?



Respostas:


307

Você precisa do catcomando (abreviação de concatenar), com redirecionamento de shell ( >) no seu arquivo de saída

cat 1.txt 2.txt 3.txt > 0.txt

8
deve estar >> certo? e também por que há uma nova linha antes de todo o texto no meu arquivo 0.txt?
Steam

1
você quer preservar o conteúdo do 0.txt?
sehe

13
@ blasto depende. Você usaria >>para anexar um arquivo para outro, onde > substitui o arquivo de saída com o que está direcionado para ele. Quanto à nova linha, há uma nova linha como o primeiro caractere no arquivo 1.txt? Você pode descobrir usando od -ce ver se o primeiro caractere é a \n.
radical7

1
@ radical7 Obrigado. Na verdade, meus arquivos são como foo_1, foo_2, foo_3. Tentei modificar seu código como - cat "$ filename _" {1,2,3} ". Txt", mas não funcionou.
Steam

1
@ Blasto Você definitivamente está indo na direção certa. O Bash certamente aceita o formulário {...}para correspondência de nome de arquivo, então talvez as aspas tenham atrapalhado um pouco o seu script? Eu sempre tento trabalhar com coisas como essa usando lsum shell. Quando eu recebo o comando corretamente, apenas recorto e colo em um script como está. Você também pode achar a -xopção útil em seus scripts - ela fará eco dos comandos expandidos no script antes da execução.
radical7

97

Outra opção, para aqueles que ainda se deparam com este post como eu, é usar find -exec:

find . -type f -name '*.txt' -exec cat {} + >> output.file

No meu caso, eu precisava de uma opção mais robusta que visse vários subdiretórios, então optei por usá-lo find. Dividindo:

find .

Procure no diretório de trabalho atual.

-type f

Interessado apenas em arquivos, não em diretórios etc.

-name '*.txt'

Reduzir o resultado definido pelo nome

-exec cat {} +

Execute o comando cat para cada resultado. "+" significa que apenas 1 instância caté gerada (thx @gniourf_gniourf)

 >> output.file

Conforme explicado em outras respostas, anexe o conteúdo do catálogo ao final de um arquivo de saída.


10
Existem muitas falhas nesta resposta. Primeiro, o curinga *.txtdeve ser citado (caso contrário, todo o findcomando, como está escrito, é inútil). Outra falha vem de um grande equívoco: o comando que é executado não é cat >> 0.txt {} , mas cat {}. Seu comando é de fato equivalente a { find . -type f -name *.txt -exec cat '{}' \; ; } >> 0.txt(adicionei agrupamento para que você perceba o que realmente está acontecendo). Outra falha é findencontrar o arquivo 0.txte catreclamará dizendo que o arquivo de entrada é um arquivo de saída .
Gnourf_gniourf

Obrigado pelas correções. Meu caso era um pouco diferente e eu não tinha pensado em algumas dessas dicas aplicadas a esse caso.
precisa saber é o seguinte

Você deve colocar >> output.fileno final do seu comando, para não induzir ninguém (inclusive você) a pensar que findserá executado cat {} >> output.filepara cada arquivo encontrado.
gniourf_gniourf

Começando a parecer muito bom! Uma sugestão final: use em -exec cat {} +vez de -exec cat {} \;, para que apenas uma instância de catseja gerada com vários argumentos ( +é especificado pelo POSIX ).
Gniourf_gniourf #

3
Boa resposta e aviso - modifiquei o meu para: find . -type f -exec cat {} + >> outputfile.txte não consegui descobrir por que meu arquivo de saída não parava de crescer nos shows, mesmo que o diretório tivesse apenas 50 megas. Foi porque eu continuei anexando outputfile.txt a si mesmo! Portanto, certifique-se de nomear esse arquivo corretamente ou colocá-lo em outro diretório completamente para evitar isso.
Thisisstackoverflow

43

se você tem um certo tipo de saída, faça algo assim

cat /path/to/files/*.txt >> finalout.txt

1
Lembre-se de que você está perdendo a possibilidade de manter a ordem de mesclagem. Isso pode afetá-lo se você tiver seus arquivos nomeados, por exemplo. file_1,, file_2file_11, Devido à ordem natural de classificação dos arquivos.
Emix

16

Se todos os seus arquivos estiverem em um único diretório, você pode simplesmente fazer

cat * > 0.txt

Os arquivos 1.txt, 2.txt, .. entrarão em 0.txt


Já respondeu por Eswar. Lembre-se de que você está perdendo a possibilidade de manter a ordem de mesclagem. Isso pode afetá-lo se você tiver seus arquivos nomeados, por exemplo. file_1,, file_2file_11, Devido à ordem natural de classificação dos arquivos.
Emix

10
for i in {1..3}; do cat "$i.txt" >> 0.txt; done

Encontrei esta página porque precisava juntar arquivos 952 em um. Achei que isso funcionaria muito melhor se você tiver muitos arquivos. Isso fará um loop para quantos números você precisar e usará cada um deles >> para adicionar no final de 0.txt.


você poderia usar a expansão cinta em bash para gato write {1,2,3} .txt >> 0.txt
mcheema

9

Se todos os seus arquivos tiverem nomes semelhantes, você pode simplesmente fazer:

cat *.log >> output.log

5

Outra opção é sed:

sed r 1.txt 2.txt 3.txt > merge.txt 

Ou...

sed h 1.txt 2.txt 3.txt > merge.txt 

Ou...

sed -n p 1.txt 2.txt 3.txt > merge.txt # -n is mandatory here

Ou sem redirecionamento ...

sed wmerge.txt 1.txt 2.txt 3.txt

Observe que a última linha também escreve merge.txt(não wmerge.txt!). Você pode usar w"merge.txt"para evitar confusão com o nome do arquivo e-n para saída silenciosa.

Obviamente, você também pode reduzir a lista de arquivos com caracteres curinga. Por exemplo, no caso de arquivos numerados, como nos exemplos acima, você pode especificar o intervalo com chaves desta maneira:

sed -n w"merge.txt" {1..3}.txt

4

se seus arquivos contiverem cabeçalhos e você desejar removê-los no arquivo de saída, poderá usar:

for f in `ls *.txt`; do sed '2,$!d' $f >> 0.out; done

3

Se o arquivo original contiver caracteres não imprimíveis, eles serão perdidos ao usar o comando cat. Usando 'cat -v', os não imprimíveis serão convertidos em cadeias de caracteres visíveis, mas o arquivo de saída ainda não conteria os caracteres reais não imprimíveis no arquivo original. Com um pequeno número de arquivos, uma alternativa pode ser abrir o primeiro arquivo em um editor (por exemplo, vim) que lida com caracteres não imprimíveis. Em seguida, manobra para a parte inferior do arquivo e digite ": r second_file_name". Isso puxará o segundo arquivo, incluindo caracteres não imprimíveis. O mesmo poderia ser feito para arquivos adicionais. Quando todos os arquivos tiverem sido lidos, digite ": w". O resultado final é que o primeiro arquivo agora conterá o que fez originalmente, além do conteúdo dos arquivos que foram lidos.


Isso não é muito programável.
FKinternet 15/07/19

1

Se você deseja anexar o conteúdo de 3 arquivos em um arquivo, o seguinte comando será uma boa opção:

cat file1 file2 file3 | tee -a file4 > /dev/null

Ele combinará o conteúdo de todos os arquivos no arquivo4, lançando a saída do console para /dev/null.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.