Tạo đệ quy các thư mục cho tất cả các chữ cái


12

Tôi muốn tạo một thư mục theo cách mà tôi cần phải gắn nhãn các thư mục từ ađến z. Trong mỗi thư mục này, tôi cần tạo các thư mục con để chúng được gắn nhãn là aa, abv.v.

Vì vậy, ví dụ, đối với thư mục m, các thư mục con của tôi sẽ được gắn nhãn là ma, mbtối đa mz.


3
bạn không cần mkdir đầu tiên vì -p cũng đang tạo các thư mục con. Và bạn không cần lệnh cd nếu bạn sử dụng các đường dẫn abolute. Mặt khác, nó hoạt động tốt, các biến được khai báo, v.v. Phiên bản của Michael Homer ngắn hơn và có thể có hiệu suất tốt hơn, nhưng với một nhiệm vụ đơn giản như vậy, bạn sẽ đủ tốt.

1
Trước đây, có nhiều mục termininfo hơn và không có cú pháp bash {a..z} vì vậy tôi liệt kê ra /usr/share/terminfovới [az] và sử dụng đầu ra đó. Linux khá thưa thớt về số lượng đó, từng là mục nhập cho tất cả các ký tự chữ hoa và chữ thường cộng với các chữ số.
âm mưu

Câu trả lời:


19

Thử:

for x in {a..z} ; do mkdir -p $x/${x}{a..z} ; done

Bash sẽ mở rộng XXX{a..z}ra XXXa, XXXbvà vân vân. Không cần vòng lặp bên trong bạn có.

Sau đó:

$ ls
a  b  c  d  e  f  g  h  i  j  k  l  m  n  o  p  q  r  s  t  u  v  w  x  y  z
$ ls m
ma  mc  me  mg  mi  mk  mm  mo  mq  ms  mu  mw  my
mb  md  mf  mh  mj  ml  mn  mp  mr  mt  mv  mx  mz

7

Vì vậy, với bashđiều mở rộng bảng chữ cái, điều này hoạt động:

set {a..z}
for a do printf "./$a/$a%s\n" "$@"
done | xargs mkdir -p

Và nếu bạn chỉ cần gõ bảng chữ cái một lần trong dòng đầu tiên, khái niệm tương tự sẽ có thể được chuyển sang bất kỳ shell nào. Có nhiều cách khác để đến dòng đã đặt nếu bạn không muốn nhập nó như sau:

seq -sP32P 97 123|dc
a b c d e f g h i j k l m n o p q r s t u v w x y z 

... ví dụ hoạt động trong một miền địa phương ASCII. Vì vậy, bạn có thể thực hiện set $(seq -sP32P 97 123|dc)hoặc bất kỳ lệnh nào khác sẽ giúp bạn có một $IFSdanh sách riêng các đối số bạn cần, nhưng, ý tôi là, có lẽ tốt hơn là chỉ sử dụng bashđiều đó hoặc nhập nó.

Dù sao, tôi nghĩ đó là cách tôi sẽ làm nếu chỉ vì nó chỉ gọi mkdirthường xuyên khi cần thiết.

Và chỉ để chứng minh cách thức hoạt động của nó, đây là một đầu ra gỡ lỗi nhỏ của một tập nhỏ hơn:

sh -cx 'for n do printf "./$n/$n%s\n" "$@"; done|cat' -- arg1 arg2 arg3
+ for n in '"$@"'
+ printf './arg1/arg1%s\n' arg1 arg2 arg3
+ cat
+ for n in '"$@"'
+ printf './arg2/arg2%s\n' arg1 arg2 arg3
+ for n in '"$@"'
+ printf './arg3/arg3%s\n' arg1 arg2 arg3
./arg1/arg1arg1
./arg1/arg1arg2
./arg1/arg1arg3
./arg2/arg2arg1
./arg2/arg2arg2
./arg2/arg2arg3
./arg3/arg3arg1
./arg3/arg3arg2
./arg3/arg3arg3

Như bạn có thể thấy, các forvòng lặp duy nhất một lần cho mỗi chỉ số mảng tham số vị trí, mà tôi đặt ở đây bằng cách chỉ cần bàn giao shcác tham số khi gọi và ở trên với set ${positionals}. Nhưng printfnhận được cùng một mảng trong danh sách đối số của nó cho mỗi lần lặp và áp dụng chuỗi định dạng của nó cho từng đối số của nó, do đó bạn có được ngữ nghĩa của đệ quy mà không có đệ quy không cần thiết.

Và việc thêm done|commandluồng ý chí tất cả forđầu ra của vòng lặp qua đường ống theo cùng một cách done >filesẽ truyền tất cả vào một tệp - chỉ mở và đóng tệp đầu ra một lần cho toàn bộ for...donecấu trúc.


3

Từ đây , tôi đã tạo ra một kịch bản như thế này. Tuy nhiên, nếu tôi nhận được một giải pháp tao nhã, tôi sẽ chấp nhận nó như một câu trả lời.

for x in {a..z}
do
    mkdir -p /home/ramesh/$x
    cd /home/ramesh/$x
    for y in {a..z}
    do
        mkdir -p /home/ramesh/$x/$x$y
    done
done

+1, câu hỏi hay và câu trả lời hay hơn :)
Nidal

@Networker, tôi chắc chắn có một giải pháp khá tốt hơn giải pháp này. Chờ đợi một số câu trả lời của chuyên gia sẽ thực hiện công việc tương tự như câu trả lời này, nhưng sẽ trông tuyệt hơn rất nhiều :)
Ramesh

Nói một cách chính xác, không cần thiết khi bạn biết các giá trị biến sẽ là gì (và chúng là các chuỗi đơn giản), nhưng nên tập thói quen trích dẫn các biến của bạn. Bạn có thể sử dụng /home/ramesh/"$x"/"$x$y", /home/ramesh/"$x/$x$y"hoặc "/home/ramesh/$x/$x$y"- tất cả đều tương đương.
Scott

1

Trong Perl:

perl -MFile::Path=make_path -e '
    make_path(map { $l=$_; map { "$l/$l$_" } a..z } a..z)
'

File::Pathlà mô-đun cốt lõi kể từ Perl 5.001.

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.