Làm thế nào để tránh việc sử dụng mèo vô dụng khi phân tích tệp?


8

Tôi có một tập tin chứa một danh sách các thư mục. Ví dụ

/foo/bar/dir1
/foo/bar/dir2
/foo/bar/dir3

Tôi muốn tạo tất cả các thư mục này. Đây là những gì tôi đã làm:

for dir in $(cat myfile); do mkdir $dir; done

Điều gì sẽ là cách chính xác để làm điều này trong khi tránh "việc sử dụng mèo vô dụng"?

Lý tưởng nhất là câu trả lời sẽ tập trung vào Ksh88, nhưng tôi cũng quan tâm đến các shell khác


2
nếu tất cả các thư mục nằm dưới một thư mục duy nhất và rất ít thì sử dụng dấu ngoặc kép của shell. $ mkdir /foo/bar/dir{1,2,3}hoặc$ mkdir /foo/bar/{dir1,dir2,dir3}
Nikhil Mulley


Cảm ơn Gilles đã chỉ ra câu hỏi đó, tôi đã không nhận ra nó. Đối với hồ sơ, tôi đã tìm cách đọc từ một tệp không phải là một biến. Và câu hỏi của tôi là bất khả tri (nếu có bất cứ điều gì tôi đề cập ksh). Trong mọi trường hợp tôi tìm thấy câu trả lời của mình; Tôi không quen thuộc read. Trang người đàn ông sẽ làm phần còn lại.
rahmu

Câu trả lời:


13

Đề xuất sử dụng của AProgrammer xargsthường là tốt nhất, nhưng một tùy chọn khác là sử dụng chuyển hướng vào một whilevòng lặp, cho phép thực hiện các lệnh bổ sung và các biến được đặt:

while read -r dir; do mkdir $dir; done < myfile

Một ví dụ về cấu trúc phức tạp hơn sẽ là:

now=`date +%Y%m%d.%H%M%S`
while read -r dir; do
    newdistfile="/tmp/dist-`echo $dir | tr / _`.tgz"
    mv $dir ~/backups/$dir.$now &&
        mkdir $dir &&
        tar xzfC $newdistfile $dir
done < myfile

Đây không phải là điều xargscó thể làm mà không cần viết một 'chương trình trợ giúp'.


Các giới hạn của việc sử dụng xargshơn là readgì? Theo sự hiểu biết của tôi xargssẽ tạo ra một quy trình mới (không giống như readđó là một phần mềm dựng sẵn). Đây không phải là điều bạn muốn tránh sao?
rahmu

xargssẽ hoạt động trên một lệnh duy nhất, vì vậy nếu bạn muốn có một câu lệnh ghép (như nhiều hơn một, một if, whilehoặc for, v.v.) hoặc đặt một biến, thì bạn không thể sử dụng xargs. Có, xargs sẽ rẽ nhánh một câu lệnh mới, cộng với một cho một số dòng đầu vào, rất ít chi phí. Tuy nhiên, một số phiên bản cũ hơn xargskhông có -0tùy chọn, vì vậy while readsẽ là cách để đi nếu có thể có khoảng trắng trong tên thư mục đầu vào.
Arcege

11

Tôi sẽ làm một cái gì đó như

xargs mkdir < myfile

1
Tại sao "-n 1"? Bạn có thể thực hiện một số thư mục với một lệnh gọi của mkdir.
ddeimeke

1
@ddeimeke, vì tôi không nhớ đó là POSIX hay chỉ là một tiện ích mở rộng phổ biến. Bây giờ tôi đã kiểm tra và nó đang ở trong SUSv2.
AProgrammer

3
Sử dụng vô dụng của xargs. ;)
người dùng không xác định

11

Ít nhất là trong bash, miễn là không có tên tệp nào chứa khoảng trắng và dòng mới, điều này:

mkdir $(< myfile) 

làm. Vì vậy, chúng tôi có một sử dụng vô dụng của for, xargsquá.

<không bắt đầu một quy trình mới trong bash, ngược lại cat, nhưng tôi không biết ksh.


2
+1 để làm rõ, trái ngược với câu trả lời khác, vấn đề khoảng trắng.
enzotib

4

Đây là giải pháp gần hơn với kịch bản gốc của bạn vẫn tránh được con mèo vô dụng

for dir in $(<myfile); do mkdir $dir; done

Nó vẫn chứa một vòng lặp vô dụng mặc dù.


2

Tôi sẽ không nói rằng đó là việc sử dụng mèo vô dụng.

Theo nghĩa cổ điển , UUOC có nghĩa là viết:

cat file | some_command and its args ...

thay vì tương đương và rẻ hơn

<file some_command and its args ...

hoặc (tương đương và kinh điển hơn)

some_command and its args ... < file

Trong trường hợp này:

for dir in $(cat myfile); do mkdir $dir; done

không có lệnh nào mà đầu ra của catđang được dẫn.

Chắc chắn có những lựa chọn thay thế không sử dụng cat. Đặc biệt, đối với bash và ksh $(<myfile)có khả năng nhanh hơn $(cat myfile), mặc dù không phải tất cả các shell đều hỗ trợ cấu trúc đó. Nhưng tôi sẽ không gọi mã gốc là "sử dụng con mèo vô dụng" nhiều hơn tôi gọi giải pháp của AProgrammer là "sử dụng xargs vô dụng".


1

Với bash4 và giới hạn bởiARG_MAX

mapfile -t <file && mkdir -- "${MAPFILE[@]}"

hoặc zmodload zsh/mapfile && mkdir -- ${(f)mapfile[infile]}nếu vỏ làzsh
don_crissti
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.