Como copio o conteúdo de cada arquivo de 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 nessa lista para outro arquivo chamado all_compounds.sdf.

Como devo fazer isso na linha de comando?

Ramita Rajaa
fonte

Respostas:

20

Não use simples substituição de comando para obter nomes de arquivos (que podem 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 readloop:

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

Para usar a substituição de comandos com segurança, defina pelo menos IFSapenas a nova linha e desative o globbing (expansão de 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.

muru
fonte
14

Maneira rápida e suja ...

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

Observe: isso só funciona se os nomes de arquivos da sua lista forem muito bem comportados - as coisas darão errado se houver espaços, novas linhas ou caracteres que tenham um significado especial para o shell - use esta resposta para obter resultados confiáveis)

Notas

  • catcon cat enates files. Também imprime seu conteúdo.
  • Usando a substituição de comando, command2 $(command1)você pode passar 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 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 teecom a -aopção caso seu arquivo já exista - isso é anexado ao arquivo em vez de sobrescrevê-lo, se ele já existir)

Zanna
fonte
11
@Zanna citar as substituições de comando para evitar a repartição de palavras, como"$(cat list_of_files.txt)"
Sergiy Kolodyazhnyy
4
@Serg se a divisão de palavras não for feita, cata lista inteira será obtida como um argumento.
Muru
@ muru OK, como lidamos com nomes de arquivos que contêm espaços, então?
Sergiy Kolodyazhnyy
11
@Serg conjunto IFS conformidade - ver o último parágrafo da minha resposta
Muru
4

Embora o GNU awkseja um utilitário de processamento de texto, ele permite executar comandos de shell externos via system()chamada. Podemos utilizar isso para nossa vantagem da seguinte forma:

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

A idéia aqui é simples: lemos o arquivo linha por linha e, em cada linha, criamos uma 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: redirecione 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
Sergiy Kolodyazhnyy
fonte