Czytanie linii z pliku tekstowego i tworzenie pliku tekstowego dla każdej nazwy w każdym wierszu

21

Załóżmy, że mam plik tekstowy typu:

john
george
james
stewert

z każdym imieniem w osobnym wierszu.

Chcę przeczytać linie tego pliku tekstowego i utworzyć plik tekstowy dla każdej nazwy, na przykład: john.txt , george.txt itd.

Jak mogę to zrobić w Bash?

    
zadawane levato 22.11.2015, 15:34
źródło

4 odpowiedzi

17

# 1 Korzystanie z Bash + touch :

while read line; do touch "$line.txt"; done <in
  • while read line; [...]; done <in : To uruchamia read , dopóki read sam nie zwróci 1 , co dzieje się, gdy dojdzie do końca pliku; dane wejściowe dla read są odczytywane z pliku o nazwie in w bieżącym katalogu roboczym zamiast z terminala ze względu na przekierowanie <in ;
  • touch "$line.txt" : To uruchamia touch na rozwiniętej wartości $line.txt , która jest zawartością line , po której następuje .txt ; touch utworzy plik, jeśli nie istnieje i zaktualizuje swój czas dostępu, jeśli istnieje;

# 2 Używanie xargs + touch :

xargs -a in -I name touch name.txt
  • -a in : sprawia, że xargs odczytuje dane wejściowe z pliku o nazwie in w bieżącym katalogu roboczym;
  • -I name : sprawia, że xargs zastępuje każde wystąpienie name bieżącym wierszem danych wejściowych w następującym poleceniu;
  • touch name : Uruchamia touch dla zastąpionej wartości name ; utworzy plik, jeśli nie istnieje, i zaktualizuje swój czas dostępu, jeśli istnieje;
% 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
    
odpowiedział kos 22.11.2015, 15:49
źródło
18

W tym konkretnym przypadku, gdy masz tylko jedno słowo w linii, możesz także:

xargs touch < file

Pamiętaj, że to się zepsuje, jeśli twoje nazwy plików mogą zawierać spacje. W takich przypadkach użyj tego:

xargs -I {} touch {} < file

Dla przyjemności, oto kilka innych podejść (oba mogą obsługiwać dowolne nazwy plików, w tym linie ze spacjami):

  • Perl

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

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

Zwróć uwagę, że w systemach Linux i podobnych systemach rozszerzenie jest opcjonalne w przypadku większości plików. Nie ma powodu, aby dodawać rozszerzenie .txt do pliku tekstowego. Możesz to zrobić, ale nie ma to żadnej różnicy. Tak więc, jeśli chcesz mimo to uzyskać rozszerzenie, użyj jednego z:

xargs -I {} touch {}.txt < file
perl -ne ''touch "$_.txt"'' file
awk '{printf "" > $0".txt"}' file 
    
odpowiedział terdon 22.11.2015, 17:58
źródło
7

AWK jest również odpowiedni do tego zadania:

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

Inny sposób, tee . Zauważ, że to podejście zostanie przerwane, jeśli linia zawiera więcej niż jeden ciąg znaków w liście plików.

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


testerdir:$ ls
filelist  george  james  john  stewert

Alternatywnie, można również wykonać </dev/null tee $(cat filelist) , jeśli chcesz uniknąć potoków

Podejście

cp /dev/null (Jak wykazałem, działa to w przypadku nazw plików zawierających spacje):

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
    
odpowiedział Sergiy Kolodyazhnyy 22.11.2015, 18:06
źródło
7
% bl0ck_qu0te%

Powiedzmy, że mam odpowiedź ;)

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

Wodoodporne również ze spacjami i przyrostkiem =)

    
odpowiedział A.B. 22.11.2015, 18:04
źródło

Przeczytaj inne pytania na temat tagów