Lettura di righe da un file di testo e creazione di un file di testo per ciascun nome su ciascuna riga


21

Diciamo che ho un file di testo come:

john
george
james
stewert

con ogni nome su una riga separata.

Voglio leggere le righe di questo file di testo e creare un file di testo per ciascun nome, come: john.txt, george.txtetc.

Come posso farlo in Bash?


2
Ti serve l'estensione? Non vi è alcun motivo per cui i file di testo abbiano un'estensione txt in Linux.
terdon,

Risposte:


18

# 1 Usando Bash + touch:

while read line; do touch "$line.txt"; done <in
  • while read line; [...]; done <in: Questo viene eseguito readfino a quando readnon viene restituito 1, ciò accade quando viene raggiunta la fine del file; l'input per readviene letto da un file denominato innella directory di lavoro corrente anziché dal terminale a causa del <inreindirizzamento;
  • touch "$line.txt": Viene eseguito touchsul valore espanso di $line.txt, ovvero il contenuto di lineseguito da .txt; touchcreerà il file se non esistente e aggiornerà il suo tempo di accesso se esistente;

# 2 Uso di xargs+ touch:

xargs -a in -I name touch name.txt
  • -a in: fa xargsleggere il suo input da un file chiamato innella directory di lavoro corrente;
  • -I name: fa xargssostituire ogni ricorrenza di namecon l'attuale riga di input nel seguente comando;
  • touch name: Viene eseguito touchsul valore sostituito di name; creerà il file se non esistente e aggiornerà il suo tempo di accesso se esistente;
% 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

come read lineleggerà effettivamente la riga? @kos
kashish,

@kashish <inafter donefa readin whilecondizione di loop leggere e memorizzare una riga da indentro linead ogni iterazione; in questo modo, touch "$line.txt"all'interno del loop verrà espanso alla riga di lettura con .txtalla fine.
kos,

farà da while read line; do touch "$line.txt"; done <insolo il lavoro? Dov'è il file sorgente?
kashish,

@kashish Certo, sono metodi alternativi: devi usare l'uno o l'altro.
kos,

1
@kashish è così che readfunziona. Vedere help read.
terdon,

18

In questo caso particolare, dove hai una sola parola per riga, puoi anche fare:

xargs touch < file

Nota che questo si interromperà se i nomi dei tuoi file possono contenere spazi. Per tali casi, utilizzare questo invece:

xargs -I {} touch {} < file

Solo per divertimento, ecco un paio di altri approcci (entrambi in grado di gestire nomi di file arbitrari, comprese le linee con spazi):

  • Perl

    perl -ne '`touch "$_"`' file
  • awk

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

Si noti che su Linux e sistemi simili, l'estensione è facoltativa per la stragrande maggioranza dei file. Non vi è alcun motivo per aggiungere .txtun'estensione a un file di testo. Sei libero di farlo, ma non fa alcuna differenza. Quindi, se vuoi comunque l'estensione, usa uno di:

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

7

AWK è appropriato anche per questa attività:

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

Un altro modo, tee. Si noti che questo approccio si interromperà se una riga contiene più di una stringa nell'elenco file.

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


testerdir:$ ls
filelist  george  james  john  stewert

In alternativa, </dev/null tee $(cat filelist)può essere fatto anche se si desidera evitare le tubazioni

cp /dev/null approccio (come ho dimostrato, funziona con nomi di file che contengono spazi):

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 ogni riga nel file contiene esattamente una stringa per riga, quindi crea un file per riga. È effettivamente uguale a echo "" | tee file1 file2 file2. Ma si rompe se i nomi dei file contengono spazi.
Sergiy Kolodyazhnyy,

7

Diciamo che ho un file di testo ...

Diciamo, ho una risposta ;)

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

Impermeabile anche con spazi e con un suffisso =)

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.