Secara rekursif membuat direktori untuk semua huruf

12

Saya ingin membuat direktori sedemikian rupa sehingga saya perlu memberi label pada direktori dari ake z. Di dalam masing-masing direktori ini, saya perlu membuat sub-direktori sehingga mereka diberi label aa, abdll.

Jadi, misalnya, untuk direktori m, sub-direktori saya akan diberi label sebagai ma, mbupto mz.

Ramesh
sumber
3
Anda tidak memerlukan mkdir pertama karena -p juga membuat subdirektori. Dan Anda tidak perlu perintah cd jika Anda menggunakan jalur abolute. Kalau tidak, itu bagus, berfungsi, variabel dideklarasikan, dll. Versi Michael Homer lebih pendek dan mungkin memiliki kinerja yang lebih baik, tetapi untuk tugas yang sederhana milik Anda akan cukup baik.
1
Kembali pada hari itu ada lebih banyak entri termininfo dan tidak ada sintaks bash {a..z} jadi saya akan mendaftar /usr/share/terminfodengan [az] dan menggunakan output itu. Linux cukup jarang dalam hitungan itu, dulu merupakan entri untuk semua karakter huruf besar dan kecil ditambah digit.
schemathings

Jawaban:

19

Mencoba:

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

Bash akan memperluas XXX{a..z}untuk XXXa, XXXbdan sebagainya. Tidak perlu untuk loop dalam yang Anda miliki.

Setelah itu:

$ 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
Michael Homer
sumber
7

Jadi, dengan bashekspansi alfabet, ini berfungsi:

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

Dan jika Anda cukup mengetikkan alfabet satu kali di baris pertama, konsep yang sama harus portabel untuk semua shell. Ada cara lain untuk sampai pada garis yang ditetapkan jika Anda tidak ingin mengetiknya seperti:

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 

... misalnya berfungsi di lokal ASCII. Jadi Anda bisa melakukan set $(seq -sP32P 97 123|dc)atau perintah lain yang akan membuat Anda $IFSdaftar terpisah dari argumen yang Anda butuhkan, tapi, maksud saya, mungkin lebih baik hanya menggunakan bashhal itu atau mengetiknya.

Bagaimanapun, saya pikir itulah cara saya akan melakukannya jika hanya karena itu hanya memanggil mkdirsesering yang diperlukan.

Dan hanya untuk mendemonstrasikan cara kerjanya, berikut adalah sedikit hasil debug dari kumpulan yang lebih kecil:

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

Seperti yang Anda lihat, forsatu - satunya loop sekali per indeks posisi parameter array, yang saya set di sini hanya dengan menyerahkan shparameter saat doa, dan di atas dengan set ${positionals}. Tetapi printfmenerima array yang sama dalam daftar argumennya untuk setiap iterasi dan menerapkan format string untuk setiap argumennya, sehingga Anda mendapatkan kemiripan rekursi tanpa rekursi yang tidak perlu.

Dan menambahkan done|commandakan mengalirkan semua forkeluaran loop di atas pipa dengan cara yang sama done >fileakan mengalirkan semuanya ke dalam file - hanya membuka dan menutup file output sekali untuk seluruh for...donekonstruksi.

mikeserv
sumber
3

Dari sini , saya akhirnya membuat skrip seperti ini. Namun, jika saya mendapatkan solusi yang elegan, saya akan menerimanya sebagai jawaban.

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
Ramesh
sumber
+1, pertanyaan bagus dan jawaban yang lebih baik :)
Nidal
@Networker, saya yakin ada solusi yang cukup bagus dari yang ini. Menunggu beberapa jawaban ahli yang akan melakukan pekerjaan sama seperti jawaban ini, tetapi akan terlihat jauh lebih keren :)
Ramesh
Sebenarnya, itu tidak perlu ketika Anda tahu apa nilai variabel akan menjadi (dan mereka adalah string sederhana), tetapi itu ide yang baik untuk membiasakan diri mengutip variabel Anda. Anda dapat menggunakan /home/ramesh/"$x"/"$x$y",, /home/ramesh/"$x/$x$y"atau "/home/ramesh/$x/$x$y"- semuanya setara.
Scott
1

Dalam Perl:

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

File::Pathadalah modul inti sejak itu Perl 5.001.

cuonglm
sumber