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 ?

Vapor
fonte
Outra resposta aqui: stackoverflow.com/questions/2576693/…
Nikos C.

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
radical7
fonte
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.

mopo922
fonte
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
Eswar Yaganti
fonte
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

Pooja
fonte
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.

freddythunder
fonte
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
AeaRy
fonte
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
Fran
fonte
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
brunocrt
fonte
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.

BACooper
fonte
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.

Ajit K'sagar
fonte