Lesen von Zeilen aus einer Textdatei und Erstellen einer Textdatei für jeden Namen in jeder Zeile

21

Angenommen, ich habe eine Textdatei wie:

john
george
james
stewert

mit jedem Namen in einer separaten Zeile.

Ich mag die Zeilen dieser Textdatei lesen und eine Textdatei für jeden Namen erstellen, wie: john.txt, george.txtusw.

Wie kann ich das in Bash machen?

levato
quelle
2
Benötigen Sie die Erweiterung? Es gibt keinen Grund, warum Textdateien unter Linux eine txt-Erweiterung haben.
Terdon

Antworten:

18

# 1 Mit Bash + touch:

while read line; do touch "$line.txt"; done <in
  • while read line; [...]; done <in: Dies wird ausgeführt, readbis sich readselbst zurückgibt. Dies 1geschieht, wenn das Ende der Datei erreicht ist. Die Eingabe für readwird inaufgrund der <inUmleitung aus einer Datei gelesen, die im aktuellen Arbeitsverzeichnis benannt ist, und nicht aus dem Terminal .
  • touch "$line.txt": Dies läuft touchauf dem erweiterten Wert von $line.txt, der der Inhalt von linegefolgt von ist .txt; toucherstellt die Datei, falls nicht vorhanden, und aktualisiert die Zugriffszeit, falls vorhanden;

# 2 Mit xargs+ touch:

xargs -a in -I name touch name.txt
  • -a in: xargsliest seine Eingabe aus einer Datei, die inim aktuellen Arbeitsverzeichnis benannt ist;
  • -I name: lässt xargsjedes Vorkommen von namedurch die aktuelle Eingabezeile im folgenden Befehl ersetzen ;
  • touch name: Läuft touchmit dem ersetzten Wert von name; Es erstellt die Datei, falls nicht vorhanden, und aktualisiert die Zugriffszeit, falls vorhanden.
% 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
quelle
Wie wird read linedie Zeile tatsächlich gelesen? @kos
kashish
@kashish <innach doneFabrikate readin der whileSchleifenbedingung lesen und speichert eine Zeile von inin linejeder Iteration an; Auf diese Weise wird das touch "$line.txt"Innere der Schleife bis zur Lesezeile mit .txtam Ende erweitert.
Kos
wird while read line; do touch "$line.txt"; done <inallein die Arbeit erledigen? Wo ist die Quelldatei?
kashish
@kashish Sicher, es handelt sich um alternative Methoden: Sie sollten entweder die eine oder die andere verwenden.
Kos
1
@kashish so readfunktioniert das Sehen help read.
Terdon
18

In diesem speziellen Fall, in dem Sie nur ein Wort pro Zeile haben, können Sie auch Folgendes tun:

xargs touch < file

Beachten Sie, dass dies fehlschlägt, wenn Ihre Dateinamen Leerzeichen enthalten können. Verwenden Sie in solchen Fällen stattdessen Folgendes:

xargs -I {} touch {} < file

Nur zum Spaß hier ein paar andere Ansätze (beide können beliebige Dateinamen verarbeiten, einschließlich Zeilen mit Leerzeichen):

  • Perl

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

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

Beachten Sie, dass die Erweiterung unter Linux und ähnlichen Systemen für die meisten Dateien optional ist. Es gibt keinen Grund .txt, einer Textdatei eine Erweiterung hinzuzufügen . Sie können dies tun, aber es macht überhaupt keinen Unterschied. Wenn Sie die Erweiterung trotzdem benötigen, verwenden Sie eine der folgenden Optionen:

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

AWK ist auch für diese Aufgabe geeignet:

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

Ein anderer Weg tee. Beachten Sie, dass dieser Ansatz abbricht, wenn eine Zeile mehr als eine Zeichenfolge in der Dateiliste enthält.

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


testerdir:$ ls
filelist  george  james  john  stewert

Alternativ </dev/null tee $(cat filelist)können Sie dies auch tun, wenn Sie Rohrleitungen vermeiden möchten

cp /dev/null Vorgehensweise (Wie ich demonstriere, funktioniert dies mit Dateinamen, die Leerzeichen enthalten):

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
quelle
1
@kos Wenn jede Zeile in der Datei genau einen String pro Zeile enthält, wird eine Datei pro Zeile erstellt. Es ist praktisch dasselbe wie echo "" | tee file1 file2 file2. Es funktioniert jedoch nicht, wenn Dateinamen Leerzeichen enthalten.
Sergiy Kolodyazhnyy
7

Nehmen wir an, ich habe eine Textdatei ...

Sagen wir mal, ich habe eine Antwort ;)

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

Wasserdicht auch mit Leerzeichen und Suffix =)

AB
quelle