Đọc các dòng từ tệp văn bản và tạo tệp văn bản cho mỗi tên trên mỗi dòng


21

Giả sử tôi có một tệp văn bản như:

john
george
james
stewert

với mỗi tên trên một dòng riêng biệt.

Tôi muốn đọc các dòng của tệp văn bản này và tạo một tệp văn bản cho mỗi tên, như : john.txt, george.txtv.v.

Làm thế nào tôi có thể làm điều này trong Bash?


2
Bạn có cần phần mở rộng? Không có lý do gì để các tệp văn bản có phần mở rộng txt trong Linux.
terdon

Câu trả lời:


18

# 1 Sử dụng Bash + touch:

while read line; do touch "$line.txt"; done <in
  • while read line; [...]; done <in: Điều này chạy readcho đến khi readchính nó trở lại 1, xảy ra khi đạt đến cuối tập tin; đầu vào cho readđược đọc từ một tệp có tên introng thư mục làm việc hiện tại thay vì từ thiết bị đầu cuối do <inchuyển hướng;
  • touch "$line.txt": Điều này chạy touchtrên giá trị mở rộng của $line.txt, đó là nội dung linetheo sau .txt; touchsẽ tạo tập tin nếu không tồn tại và cập nhật thời gian truy cập nếu có;

# 2 Sử dụng xargs+ touch:

xargs -a in -I name touch name.txt
  • -a in: làm cho xargsđọc đầu vào của nó từ một tệp có tên introng thư mục làm việc hiện tại;
  • -I name: thực hiện xargsthay thế mọi lần xuất hiện namebằng dòng đầu vào hiện tại trong lệnh sau;
  • touch name: Chạy touchtrên giá trị thay thế của name; nó sẽ tạo tập tin nếu không tồn tại và cập nhật thời gian truy cập nếu có;
% 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

Làm thế nào read linethực sự sẽ đọc dòng? @kos
kashish

@kashish <insau khi donethực hiện readtrong whileđiều kiện vòng lặp đọc và lưu trữ một dòng từ introng linemỗi lần lặp; bằng cách này, touch "$line.txt"bên trong vòng lặp sẽ được mở rộng đến dòng đọc .txtở cuối.
kos

sẽ while read line; do touch "$line.txt"; done <inmột mình làm công việc? Tập tin nguồn ở đâu?
kashish

@kashish Chắc chắn, chúng là các phương pháp thay thế: bạn có nghĩa là sử dụng cái này hay cái kia.
kos

1
@kashish đó là cách làm readviệc. Xem help read.
terdon

18

Trong trường hợp cụ thể này, khi bạn chỉ có một từ duy nhất trên mỗi dòng, bạn cũng có thể thực hiện:

xargs touch < file

Lưu ý rằng điều này sẽ phá vỡ nếu tên tệp của bạn có thể chứa dấu cách. Đối với những trường hợp như vậy, sử dụng điều này thay thế:

xargs -I {} touch {} < file

Để cho vui, đây là một vài cách tiếp cận khác (cả hai đều có thể xử lý tên tệp tùy ý, bao gồm các dòng có khoảng trắng):

  • Perl

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

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

Lưu ý rằng trên Linux và các hệ thống tương tự, tiện ích mở rộng là tùy chọn cho phần lớn các tệp. Không có lý do để thêm một .txtphần mở rộng vào một tệp văn bản. Bạn có thể tự do làm điều đó nhưng nó không có gì khác biệt cả. Vì vậy, nếu bạn muốn tiện ích mở rộng, hãy sử dụng một trong:

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

7

AWK cũng thích hợp cho nhiệm vụ này:

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

Một cách khác , tee. Lưu ý rằng cách tiếp cận này sẽ bị hỏng nếu một dòng chứa nhiều hơn một chuỗi trong filelist.

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


testerdir:$ ls
filelist  george  james  john  stewert

Ngoài ra, </dev/null tee $(cat filelist)có thể được thực hiện là tốt, nếu bạn muốn tránh đường ống

cp /dev/null Cách tiếp cận (Như tôi chứng minh điều này không hoạt động với tên tệp có chứa khoảng trắng):

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 nếu mỗi dòng trong tệp chứa chính xác một chuỗi trên mỗi dòng, thì nó sẽ tạo một tệp trên mỗi dòng. Nó có hiệu lực tương tự như echo "" | tee file1 file2 file2. Nhưng nó sẽ phá vỡ nếu tên tệp chứa khoảng trắng.
Sergiy Kolodyazhnyy

7

Giả sử tôi có một tập tin văn bản

Hãy nói, tôi có một câu trả lời ;)

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

Không thấm nước cũng có không gian và có hậu tố =)

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.