Читання рядків з текстового файлу та створення текстового файлу для кожного імені в кожному рядку


21

Скажімо, у мене є текстовий файл на зразок:

john
george
james
stewert

з кожним іменем в окремому рядку.

Я хочу читати рядки цього текстового файлу і створити текстовий файл для кожного імені, наприклад: john.txt, і george.txtт.д.

Як я можу це зробити на Bash?


2
Вам потрібне розширення? Немає причини текстові файли мати розширення txt в Linux.
тердон

Відповіді:


18

# 1 Використання Bash + touch:

while read line; do touch "$line.txt"; done <in
  • while read line; [...]; done <in: Це працює, readпоки readсам не повернеться 1, що відбувається, коли досягне кінець файлу; вхід для readзчитується з файлу, названого inв поточному робочому каталозі, а не з терміналу через <inперенаправлення;
  • touch "$line.txt": Це працює touchна розширеному значенні $line.txt, яке є змістом, за lineяким слід .txt; touchстворить файл, якщо він не існує, і оновить його час доступу, якщо він існує;

# 2 Використання xargs+ touch:

xargs -a in -I name touch name.txt
  • -a in: змушує xargsчитати свої дані з файлу, названого inв поточному робочому каталозі;
  • -I name: змушує xargsзамінювати кожне виникнення nameпоточного рядка введення в наступній команді;
  • touch name: Працює touchна заміненому значенні name; він створить файл, якщо він не існує, і оновить його час доступу, якщо він існує;
% 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

як read lineнасправді буде читати рядок? @kos
kashish

@kashish <inafter doneвносить readу whileциклі умови зчитування та збереження одного рядка з inу lineпід час кожної ітерації; таким чином, touch "$line.txt"всередині циклу буде розширено до рядка читання з .txtкінця.
kos

буде while read line; do touch "$line.txt"; done <inодин робити роботу? Де знаходиться вихідний файл?
кашиш

@kashish Звичайно, це альтернативні методи: вам призначено використовувати той чи інший.
kos

1
@kashish так readпрацює. Див help read.
тердон

18

У цьому конкретному випадку, коли у вас є лише одне слово на рядок, ви також можете зробити:

xargs touch < file

Зауважте, що це порушиться, якщо імена файлів можуть містити пробіли. Для таких випадків використовуйте це замість:

xargs -I {} touch {} < file

Для задоволення, ось кілька інших підходів (обидва з яких можуть обробляти довільні назви файлів, включаючи рядки з пробілами):

  • Perl

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

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

Зауважте, що на Linux та подібних системах розширення необов’язкове для більшості файлів. Немає підстав додавати .txtрозширення до текстового файлу. Ви можете це зробити, але це зовсім не має ніякого значення. Отже, якщо ви все-таки хочете розширення, скористайтеся одним із:

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

7

AWK також підходить для цього завдання:

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

Інший спосіб tee. Зауважте, що цей підхід порушиться, якщо рядок містить більше одного рядка у списку файлів.

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


testerdir:$ ls
filelist  george  james  john  stewert

Крім того, </dev/null tee $(cat filelist)це можна зробити також, якщо ви хочете уникати трубопроводів

cp /dev/null підхід (Як я демонструю, це працює з іменами файлів, які містять пробіли):

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, якщо кожен рядок у файлі містить рівно один рядок на рядок, то він створює файл у рядку. Це ефективно повністю те саме, що echo "" | tee file1 file2 file2. Але він порушується, якщо в назви файлів містяться пробіли.
Сергій Колодяжний

7

Скажімо, у мене є текстовий файл ...

Скажімо, у мене є відповідь ;)

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

Водонепроникний також з пробілами та з суфіксом =)

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.