Tworzenie licznych katalogów za pomocą mkdir

14

Chciałbym utworzyć wiele katalogów za pomocą mkdir. Każda nazwa katalogu będzie się składać z prefiksu (ciąg) i indeksu (liczba całkowita). Załóżmy, że chciałbym, aby prefiks był „s”, a indeksy zawierały się w przedziale od 1 do 50. Oznacza to, że chciałbym utworzyć katalogi zatytułowane:

s1,, s2... s49,,s50

Czy istnieje sposób, aby to zrobić automatycznie przy użyciu mkdir? Dziękuję za Twój czas.

Andrzej
źródło
2
Jakiej powłoki używasz?
Francesco Turco
@FrancescoTurco Używam bash. Dziękuję za Twój czas!
Andrew
3
FYI, uważam, że o wiele bardziej przydatne do wykorzystania wskaźników stałej szerokości, jak: s01, s02, ..., s49, s50. Gdybym użył wskaźników o stałej szerokości, /bin/lsprawie zawsze generuje pożądane zamówienie.
Rob

Odpowiedzi:

32

Możesz to zrobić za pomocą skryptu powłoki.

Pure sh - zadziała to nawet na powłokach Bourne'a sprzed POSIX:

n=1;
max=50;
while [ "$n" -le "$max" ]; do
  mkdir "s$n"
  n=`expr "$n" + 1`;
done

Jeśli chcesz utworzyć dużą liczbę katalogów, możesz przyspieszyć skrypt, redukując go do pojedynczego wywołania, mkdira także używając wbudowanych powłok do testowania i arytmetyki. Lubię to:

n=1
max=50
set -- # this sets $@ [the argv array] to an empty list.

while [ "$n" -le "$max" ]; do
    set -- "$@" "s$n" # this adds s$n to the end of $@
    n=$(( $n + 1 ));
done 

mkdir "$@"

Zsh, ksh93 lub bash sprawiają, że jest to o wiele łatwiejsze, ale powinienem zauważyć, że nie jest to wbudowane mkdiri może nie działać w innych powłokach. W większych przypadkach może na to również wpływać ograniczenie liczby lub całkowitej wielkości argumentów, które mogą być przekazywane do polecenia.

mkdir s{1..50}
Losowo 832
źródło
3
+1 To jest świetne! Muszę jednak podchwycić jedną rzecz: n=$(( n + 1 ))byłby tak samo POSIX i nie kosztowałby cię podpowłoki.
kojiro
@rahmu [[słowem kluczowym nie jest POSIX. (Nie wspominając o tym, że [ jest to powłoka wbudowana w wiele nowoczesnych powłok).
kojiro
@kojiro: [[działa na moim ksh88(który poprzedza bash), więc założyłem, że to POSIX. Nie mogłem znaleźć żadnej wzmianki o tym w specyfikacji POSIX, więc uważam, że masz rację. Dzięki za informację!
rahmu
Myślałem o dodaniu wersji z rozszerzeniem arytmetycznym, ale chciałem ograniczyć „czyste sh” do rzeczy, które działałyby również w wersjach wcześniejszych niż POSIX. Nie wspominałem też o seq z tego samego powodu - jeśli masz seq, prawdopodobnie masz bash. Przykład pętli jest również dobry do ominięcia limitów argumentów dla większej liczby katalogów, co oznacza również, że jest miejsce for i in {range}dla użytkowników zaawansowanych powłok.
Random832
Wskazówka zsh na końcu jest niesamowita, dzięki czemu zaoszczędziłem tyle czasu!
Jase
33
  • Jeden

    for i in {1..50}; do
      mkdir s"$i"
    done
  • Dwa

    mkdir s{1..50}

    Ta opcja działa w bash , zsh i ksh93

  • Trzy

    mkdir $(printf "s%02i " $(seq 1 50))
Jhonathan
źródło
4
Dlaczego miałbyś kiedykolwiek używać jednego na dwóch?
Kevin,
7
możesz chcieć zrobić więcej $iniż zrobić katalog np mkdir s$i ; echo $i > s$i/$i. Ponadto One jest ładnym, prostym przykładem użycia pętli for w bash ... w takiej witrynie nie jest mało prawdopodobne, aby początkujący użytkownik go zobaczył i pomyślał: „fajnie, nie zdawałem sobie sprawy, że możesz to zrobić „---> oświecenie.
cas
1
@rahmu Jest to funkcja znaleziona w Bash / Zsh (prawdopodobnie także ksh93). Nie trzeba głosować.
helpermethod
3
@rahmu: Myślę, że należy wziąć pod uwagę tylko to, czy odpowiedź jhonathan rozwiązuje problem z powłoką PO (bash), niekoniecznie z innymi.
Francesco Turco,
4
@Kevin, chociaż nie będzie to problem dla pięćdziesięciu, jeśli masz pięćset katalogów, które mogą sprawić, że będziesz się martwić limitami argumentów.
Random832
10

Wiele skomplikowanych odpowiedzi tutaj, ale bash sprawia, że ​​jest to naprawdę łatwe. Jasne, czyste rozwiązanie POSIX działa, ale dlaczego nie skorzystać z bashpowłoki, której używasz? Możesz to zrobić z łatwością dzięki nawiasowi klamrowemu :

% mkdir -v s{1..10} && ls -1d s{1..10}                                   (09-24 17:37)
mkdir: created directory `s1'
mkdir: created directory `s2'
mkdir: created directory `s3'
mkdir: created directory `s4'
mkdir: created directory `s5'
mkdir: created directory `s6'
mkdir: created directory `s7'
mkdir: created directory `s8'
mkdir: created directory `s9'
mkdir: created directory `s10'
s1
s10
s2
s3
s4
s5
s6
s7
s8
s9
laebshade
źródło
5

mkdir $(seq --format 's%.0f' 1 50)

lub jeśli chcesz liczby uzupełnione zerami (co byłoby lepsze do sortowania):

mkdir $(seq --format 's%02.0f' 1 50)

lub:

mkdir s$(seq -s ' s' -w 1 50)- zwróć uwagę na ciąg „s” tuż przed $(), bez niego pierwszym utworzonym katalogiem będzie po prostu „01” zamiast „s01”

i w końcu: mkdir $(printf "s%02i " $(seq 1 50))

seq pochodzi z GNU Coreutils

co dziwne, sekwencja --formatlub -fopcja zezwala tylko na podwójne typy zmiennoprzecinkowe printf (jak f i g. również dziwny format szesnastkowy zmiennoprzecinkowy, do którego nigdy nie znalazłem żadnego zastosowania). Nie mam pojęcia dlaczego. Byłoby miło, gdyby obsługiwał także inne printf(3)typy liczbowe, takie jak liczba całkowita (d, i), ósemkowa (o, U) lub szesnastkowa (x, X).

W każdym razie podwójny format z dokładnością dziesiętną równą %.0flub %02.0fzbliżoną do liczby całkowitej do tego celu.

$ seq --help
Zastosowanie: seq [OPCJA] ... OSTATNIE
  lub: seq [OPCJA] ... PIERWSZY OSTATNI
  lub: seq [OPCJA] ... PIERWSZE NARUSZENIE OSTATNIE
Drukuj liczby od PIERWSZEGO do OSTATNEGO, w krokach NAPRAWY.

  -f, --format = FORMAT użyj zmiennoprzecinkowego FORMATU stylu printf
  -s, --separator = STRING użyj STRING do oddzielenia liczb (domyślnie: \ n)
  -w, --equal-width wyrównuje szerokość, wypełniając wiodącymi zerami
      --help wyświetl tę pomoc i zakończ
      - informacje o wersji wyjściowej wersji i wyjście

Jeśli pominięto FIRST lub INCREMENT, domyślnie jest to 1. Oznacza to, że
pominięte INCREMENT ma wartość domyślną 1, nawet gdy LAST jest mniejsze niż FIRST.
FIRST, INCREMENT i LAST są interpretowane jako wartości zmiennoprzecinkowe.
INCREMENT jest zwykle dodatni, jeśli FIRST jest mniejszy niż LAST, oraz
INCREMENT jest zwykle ujemny, jeśli wartość FIRST jest większa niż LAST.
FORMAT musi być odpowiedni do wypisania jednego argumentu typu `double ';
domyślnie jest to% .PRECf, jeśli FIRST, INCREMENT i LAST są punktami stałymi
liczby dziesiętne z maksymalną dokładnością PREC, aw przeciwnym razie do% g.

Zobacz także: http://www.gnu.org/software/coreutils/manual/html_node/seq-invocation.html

cas
źródło
{1,50}lub {01,50}(w przypadku wypełniania zerami) jest znacznie łatwiejsze i bardziej zrozumiałe.
Kevin
1
prawda ... jeśli używasz bash zamiast sh. dlatego głosowałem na odpowiedź @ Random832. to dobra odpowiedź. użycie seq jest również przydatną odpowiedzią.
cas
4

Aby być innym, oto rozwiązanie sh POSIX, które wykorzystuje rekurencję:

makedirs() {
  [ "$1" -gt 0 ] || return
  mkdir "s$1"
  makedirs $(( $1 - 1 ))
}
$ makedirs 9
$ ls
s1  s2  s3  s4  s5  s6  s7  s8  s9
kojiro
źródło