Leer líneas de un archivo de texto y crear un archivo de texto para cada nombre en cada línea

21

Digamos que tengo un archivo de texto como:

john
george
james
stewert

con cada nombre en una línea separada.

Quiero leer las líneas de este archivo de texto y crear un archivo de texto para cada nombre, como: john.txt, george.txtetc.

¿Cómo puedo hacer esto en Bash?

levato
fuente
2
¿Necesitas la extensión? No hay ninguna razón para que los archivos de texto tengan una extensión txt en Linux.
terdon

Respuestas:

18

# 1 usando Bash + touch:

while read line; do touch "$line.txt"; done <in
  • while read line; [...]; done <in: Esto se ejecuta readhasta que readregresa 1, lo que sucede cuando se alcanza el final del archivo; la entrada para readse lee desde un archivo nombrado inen el directorio de trabajo actual en lugar de desde el terminal debido a la <inredirección;
  • touch "$line.txt": Esto se ejecuta touchen el valor expandido de $line.txt, que es el contenido de lineseguido por .txt; touchcreará el archivo si no existe y actualizará su tiempo de acceso si existe;

# 2 usando xargs+ touch:

xargs -a in -I name touch name.txt
  • -a in: hace xargsleer su entrada de un archivo nombrado inen el directorio de trabajo actual;
  • -I name: hace xargsreemplazar cada ocurrencia de namecon la línea de entrada actual en el siguiente comando;
  • touch name: Se ejecuta touchen el valor reemplazado de name; creará el archivo si no existe y actualizará su tiempo de acceso si existe;
% 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
kos
fuente
¿Cómo read lineleerá realmente la línea? @kos
kashish
@kashish <indespués de donemarcas readen la whilecondición de bucle leer y almacenar una línea de inen lineen cada iteración; de esta manera, touch "$line.txt"dentro del bucle se expandirá a la línea de lectura .txtal final.
kos
será while read line; do touch "$line.txt"; done <insolo hacer el trabajo? ¿Dónde está el archivo fuente?
kashish
@kashish Claro, son métodos alternativos: debes usar uno u otro.
kos
1
@kashish así es como readfunciona. Ver help read.
terdon
18

En este caso particular, donde solo tiene una sola palabra por línea, también puede hacer:

xargs touch < file

Tenga en cuenta que esto se romperá si los nombres de sus archivos pueden contener espacios. Para tales casos, use esto en su lugar:

xargs -I {} touch {} < file

Solo por diversión, aquí hay un par de otros enfoques (los cuales pueden manejar nombres de archivos arbitrarios, incluidas líneas con espacios):

  • Perl

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

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

Tenga en cuenta que en Linux y sistemas similares, la extensión es opcional para la gran mayoría de los archivos. No hay razón para agregar una .txtextensión a un archivo de texto. Usted es libre de hacerlo, pero no hace ninguna diferencia. Entonces, si desea la extensión de todos modos, use uno de:

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

AWK también es apropiado para esta tarea:

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

Otra forma, tee. Tenga en cuenta que este enfoque se romperá si una línea contiene más de una cadena en la lista de archivos.

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


testerdir:$ ls
filelist  george  james  john  stewert

Alternativamente, también </dev/null tee $(cat filelist)se puede hacer, si desea evitar las tuberías

cp /dev/null enfoque (como demuestro esto funciona con nombres de archivo que contienen espacios):

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
Sergiy Kolodyazhnyy
fuente
1
@kos si cada línea en el archivo contiene exactamente una cadena por línea, entonces crea un archivo por línea. Efectivamente es lo mismo que echo "" | tee file1 file2 file2. Pero se rompe si los nombres de archivo contienen espacios.
Sergiy Kolodyazhnyy
7

Digamos que tengo un archivo de texto ...

Digamos que tengo una respuesta ;)

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

Impermeable también con espacios y con sufijo =)

AB
fuente