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

21

Допустим, у меня есть текстовый файл, как:

john
george
james
stewert

с каждым именем на отдельной строке.

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

Как я могу сделать это в Bash?

levato
источник
2
Вам нужно расширение? У текстовых файлов нет причин иметь расширение txt в Linux.
Terdon

Ответы:

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условии цикла чтение и сохранение одной строки из inin lineна каждой итерации; таким образом, touch "$line.txt"внутри цикла будет расширен до строки чтения с .txtв конце.
Кос
while read line; do touch "$line.txt"; done <inодин будет делать работу? Где находится исходный файл?
Кашиш
@kashish Конечно, это альтернативные методы: вы должны использовать один или другой.
Кос
1
@kashish вот так readработает. См help read.
Terdon
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 
terdon
источник
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

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

AB
источник