Como copio o conteúdo de todos os arquivos em uma lista para outro arquivo?

15

Eu tenho uma lista de nomes de arquivos dentro de um arquivo chamado list_of_files.txt .

Eu quero copiar o conteúdo de cada arquivo dessa lista em outro arquivo chamado all_compounds.sdf .

Como devo fazer isso a partir da linha de comando?

    
por Ramita Rajaa 03.01.2017 / 08:27

3 respostas

20

Não use substituição de comando simples para obter nomes de arquivos (que poderiam facilmente quebrar com espaços e outros caracteres especiais). Use algo como xargs :

xargs -d '\n' -a list_of_files.txt cat > all_compounds.sdf

Ou um while read loop:

while IFS= read -r file; do cat "$file"; done < list_of_files.txt > all_compounds.sdf

Para usar a substituição de comando com segurança, defina pelo menos IFS apenas para a nova linha e desabilite o globbing (expansão de caractere curinga):

(set -f; IFS=$'\n'; cat $(cat list_of_files.txt) > all_compounds.sdf)

Os parênteses circundantes () devem executar isso em um subshell, para que seu shell atual não seja afetado por essas alterações.

    
por muru 03.01.2017 / 08:51
14

Maneira rápida e suja ...

cat $(cat list_of_files.txt) >> all_compounds.sdf

Por favor note: isto só funciona se os nomes dos arquivos na sua lista forem muito bem comportados - as coisas vão dar errado se eles tiverem espaços, novas linhas ou quaisquer caracteres que tenham significado especial para o shell esta resposta em vez para resultados confiáveis)

Notas

  • cat con cat combina arquivos. Também imprime seu conteúdo.
  • Usando a substituição de comando command2 $(command1) , você pode transmitir a saída de command1 ( cat list... ) para command2 ( cat ), que concatena os arquivos.
  • Em seguida, use o redirecionamento >> para enviar a saída para um arquivo em vez de imprimir para o stdout. Se você quiser ver a saída, use tee :

    cat $(cat list_of_files.txt) | tee -a all_compounds.sdf
    

(Eu usei >> em vez de > e tee com a opção -a caso seu arquivo já exista - isso anexa ao arquivo em vez de sobrescrevê-lo, se já existe)

    
por Zanna 03.01.2017 / 08:32
4

Embora o GNU awk seja um utilitário de processamento de texto, ele permite a execução de comandos externos do shell via system() call. Podemos utilizar isso a nosso favor da seguinte forma:

$ awk '{cmd=sprintf("cat \"%s\"",$0); system(cmd)}' file_list.txt                                                        

A ideia aqui é simples: lemos o arquivo linha por linha e, de cada linha, criamos a string formatada cat "File name.txt" , que é então passada para system() .

E aqui está em ação:

$ ls
file1.txt  file2.txt  file3 with space.txt  file_list.txt


$ awk '{cmd=sprintf("cat \"%s\"",$0); system(cmd)}' file_list.txt                                                        
Hi, I'm file2
Hi, I'm file1
Hi, I'm file3

Então já fizemos a grande parte da tarefa - imprimimos todos os arquivos da lista. O resto é simples: redirecionar a saída final para o arquivo com o operador > no arquivo de resumo.

awk '{cmd=sprintf("cat \"%s\"",$0); system(cmd)}' file_list.txt > output.txt
    
por Sergiy Kolodyazhnyy 03.01.2017 / 09:09