Rekurencyjnie twórz katalogi dla wszystkich liter


12

Chcę utworzyć katalog w taki sposób, że muszę oznaczyć katalogi od ado z. Wewnątrz każdego z tych katalogów, muszę utworzyć podkatalogi tak, że są one oznaczone jako aa, abetc.

Tak więc, na przykład, do katalogu m, moi podkatalogi będą oznaczone jako ma, mbdo września mz.


3
nie potrzebujesz pierwszego mkdir, ponieważ -p tworzy również podkatalogi. I nie potrzebujesz komendy cd, jeśli używasz abolutnych ścieżek. W przeciwnym razie jest to fajne, działające, zadeklarowane zmienne itp. Wersja Michaela Homera jest krótsza i może ma lepszą wydajność, ale przy tak prostym zadaniu twoje byłoby wystarczająco dobre.

1
W tamtych czasach było więcej wpisów termininfo i brak składni bash {a..z}, więc wyliczyłem /usr/share/terminfo[az] i użyłem tego wyjścia. Linux jest dość rzadki pod tym względem, kiedyś były to wpisy dla wszystkich wielkich i małych znaków plus cyfr.
schematy

Odpowiedzi:


19

Próbować:

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

Bash rozwinie XXX{a..z}się XXXa, XXXbi tak dalej. Nie ma potrzeby korzystania z wewnętrznej pętli.

Po tym:

$ 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

Tak więc w przypadku bashrozszerzenia alfabetu działa to:

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

A jeśli po prostu wpiszesz alfabet raz w pierwszym wierszu, ta sama koncepcja powinna być przenośna dla dowolnej powłoki. Istnieją inne sposoby dotarcia do ustawionej linii, jeśli nie chcesz jej wpisywać:

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 

... na przykład działa w ustawieniach ASCII. Możesz więc wykonać set $(seq -sP32P 97 123|dc)dowolną inną komendę, która da ci $IFSoddzielną listę argumentów, których potrzebujesz, ale oznacza to, że prawdopodobnie lepiej po prostu użyć tej bashrzeczy lub ją wpisać.

W każdym razie myślę, że tak właśnie bym to zrobił, choćby dlatego, że wywołuje się mkdirtak często, jak to konieczne.

Aby pokazać, jak to działa, oto mały wynik debugowania mniejszego zestawu:

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

Jak widać, forjedyne pętle raz na indeks tablicy parametrów pozycyjnych, które tutaj ustawiłem, po prostu przekazując shparametry przy wywołaniu, i powyżej za pomocą set ${positionals}. Ale printfotrzymuje tę samą tablicę z listy argumentów dla każdej iteracji i stosuje ciąg formatu do każdego z argumentów, dzięki czemu uzyskuje się pozór rekurencji bez zbędnej rekurencji.

A dodanie done|commandstrumienia przesyła strumieniowo wszystkie dane forwyjściowe pętli przez potok w ten sam sposób done >file, przesyła je strumieniowo do pliku - otwierając i zamykając plik wyjściowy tylko raz dla całej for...donekonstrukcji.


3

Od tutaj , skończyło się na tworzeniu skryptu takiego. Jeśli jednak dostanę eleganckie rozwiązanie, zaakceptuję je jako odpowiedź.

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, dobre pytanie i lepsza odpowiedź :)
Nidal

@Networker, jestem pewien, że istnieje całkiem dobre rozwiązanie niż to. Oczekiwanie na odpowiedź eksperta, która wykona zadanie tak samo jak ta odpowiedź, ale będzie wyglądać znacznie fajniej :)
Ramesh

Ściśle mówiąc, nie jest konieczne, gdy wiesz, jakie będą wartości zmiennych (i są to proste łańcuchy), ale dobrym pomysłem jest przyzwyczajenie się do cytowania zmiennych. Możesz użyć /home/ramesh/"$x"/"$x$y", /home/ramesh/"$x/$x$y"lub "/home/ramesh/$x/$x$y"- wszystkie są równoważne.
Scott

1

W Perl:

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

File::Pathod tego czasu jest modułem podstawowym Perl 5.001.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.