Lendo linhas de um arquivo de texto e criando um arquivo de texto para cada nome em cada linha

21

Digamos que eu tenha um arquivo de texto como:

john
george
james
stewert

com todos os nomes em uma linha separada.

Eu quero ler as linhas deste arquivo de texto e criar um arquivo de texto para cada nome, como: john.txt , george.txt etc.

Como posso fazer isso no Bash?

    
por levato 22.11.2015 / 15:34

4 respostas

17

# 1 usando Bash + touch :

while read line; do touch "$line.txt"; done <in
  • while read line; [...]; done <in : executa read até que read retorne 1 , o que acontece quando o final do arquivo é atingido; a entrada para read é lida de um arquivo chamado in no diretório de trabalho atual, em vez de no terminal devido ao redirecionamento <in ;
  • touch "$line.txt" : executa touch no valor expandido de $line.txt , que é o conteúdo de line seguido por .txt ; touch criará o arquivo se não existir e atualizará seu tempo de acesso, se existente;

# 2 usando xargs + touch :

xargs -a in -I name touch name.txt
  • -a in : faz xargs ler sua entrada de um arquivo chamado in no diretório de trabalho atual;
  • -I name : faz com que xargs substitua cada ocorrência de name pela linha atual de entrada no seguinte comando;
  • touch name : Executa touch no valor substituído de name ; ele criará o arquivo se não existir e atualizará seu tempo de acesso, se existente;
% ls
in
% cat in
john
george
james
stewert
% while read line; do touch "$line.txt"; done <in
% ls
george.txt  in  james.txt  john.txt  stewert.txt
% rm *.txt
% xargs -a in -I name touch name.txt
% ls
george.txt  in  james.txt  john.txt  stewert.txt
    
por kos 22.11.2015 / 15:49
18

Nesse caso específico, em que você tem apenas uma palavra por linha, também é possível fazer isso:

xargs touch < file

Observe que isso será interrompido se os nomes dos arquivos puderem conter espaços. Para tais casos, use isso:

xargs -I {} touch {} < file

Apenas por diversão, aqui estão algumas outras abordagens (ambas podem manipular nomes de arquivos arbitrários, incluindo linhas com espaços):

  • Perl

    perl -ne ''touch "$_"'' file
    
  • Awk

    awk '{printf "" > $0}' file 
    

Observe que no Linux e em sistemas semelhantes, a extensão é opcional para a grande maioria dos arquivos. Não há motivos para adicionar uma extensão .txt a um arquivo de texto. Você é livre para fazer isso, mas não faz diferença alguma. Então, se você quiser a extensão, use um dos seguintes:

xargs -I {} touch {}.txt < file
perl -ne ''touch "$_.txt"'' file
awk '{printf "" > $0".txt"}' file 
    
por terdon 22.11.2015 / 17:58
7

O AWK também é apropriado para esta tarefa:

testerdir:$ awk '{system("touch "$0)}' filelist

testerdir:$ ls
filelist  george  james  john  stewert

testerdir:$ awk '{system("touch "$0".txt")}' filelist                          

testerdir:$ ls
filelist  george.txt  james.txt  john.txt  stewert.txt
george    james       john       stewert

Outra maneira, tee . Observe que essa abordagem será interrompida se uma linha contiver mais de uma cadeia na lista de arquivos.

testerdir:$ echo "" | tee $(cat filelist)


testerdir:$ ls
filelist  george  james  john  stewert

Alternativamente, </dev/null tee $(cat filelist) pode ser feito também, se você quiser evitar a tubulação

cp /dev/null approach (Como demonstro, isso funciona com nomes de arquivos que contêm espaços):

testerdir:$ cat filelist | xargs -I {}  cp /dev/null  "{}"                     

testerdir:$ ls
filelist  FILE WITH SPACES  george  james  john  stewert

testerdir:$ ls FILE\ WITH\ SPACES                                              
FILE WITH SPACES
    
por Sergiy Kolodyazhnyy 22.11.2015 / 18:06
7

Let's say I have a text file …

Digamos que eu tenha uma resposta ;)

awk '{system("touch \""$0".txt\"")}' file

Impermeável também com espaços e com um sufixo =)

    
por A.B. 22.11.2015 / 18:04