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


21

Digamos que eu tenho 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.txtetc.

Como posso fazer isso no Bash?


2
Você precisa da extensão? Não há razão para os arquivos de texto terem uma extensão txt no Linux.
terdon

Respostas:


18

# 1 Usando o Bash + touch:

while read line; do touch "$line.txt"; done <in
  • while read line; [...]; done <in: Isso é executado readaté que readele retorne 1, o que acontece quando o final do arquivo é atingido; a entrada para readé lida a partir de um arquivo nomeado inno diretório de trabalho atual em vez de no terminal devido ao <inredirecionamento;
  • touch "$line.txt": É executado touchno valor expandido de $line.txt, que é o conteúdo de lineseguido por .txt; touchcriará o arquivo se não existir e atualizará seu tempo de acesso, se existir;

# 2 Usando xargs+ touch:

xargs -a in -I name touch name.txt
  • -a in: faz xargsler sua entrada de um arquivo nomeado inno diretório de trabalho atual;
  • -I name: xargssubstitui todas as ocorrências namepela linha de entrada atual no seguinte comando;
  • touch name: É executado touchno valor substituído de name; ele criará o arquivo se não existir e atualizará seu tempo de acesso, se existir;
% 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

como vai read linerealmente ler a linha? @kos
kashish

@kashish <indepois de donefazer readna whilecondição de loop ler e armazenar uma linha de indentro linea cada iteração; Dessa forma, o touch "$line.txt"interior do loop será expandido para a linha de leitura .txtno final.
kos

vai while read line; do touch "$line.txt"; done <insozinha fazer o trabalho? Onde está o arquivo de origem?
Kashish

@ kashish Claro, eles são métodos alternativos: você deve usar um ou outro.
kos

1
@ kashish é assim que readfunciona. Veja help read.
terdon

18

Nesse caso específico, onde você tem apenas uma única palavra por linha, também pode:

xargs touch < file

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

xargs -I {} touch {} < file

Apenas por diversão, aqui estão algumas outras abordagens (que podem lidar com 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 sistemas similares, a extensão é opcional para a grande maioria dos arquivos. Não há motivo para adicionar uma .txtextensão a um arquivo de texto. Você é livre para fazê-lo, mas isso não faz nenhuma diferença. Portanto, se você deseja a extensão de qualquer maneira, use um dos seguintes:

xargs -I {} touch {}.txt < file
perl -ne '`touch "$_.txt"`' file
awk '{printf "" > $0".txt"}' file 

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

Outro jeito tee. Observe que essa abordagem será interrompida se uma linha contiver mais de uma sequência na lista de arquivos.

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


testerdir:$ ls
filelist  george  james  john  stewert

Como alternativa, isso também </dev/null tee $(cat filelist)pode ser feito, se você quiser evitar tubulações

cp /dev/null abordagem (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

1
@kos se cada linha do arquivo contiver exatamente uma string por linha, ele criará um arquivo por linha. É efetivamente o mesmo que echo "" | tee file1 file2 file2. Mas ele quebra se os nomes de arquivos contiverem espaços.
22815 Sergiy Kolodyazhnyy

7

Digamos que eu tenho um arquivo de texto ...

Digamos Vamos, eu tenho uma resposta ;)

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

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

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.