Erstellen Sie zahlreiche Verzeichnisse mit mkdir

13

Ich möchte viele Verzeichnisse mit erstellen mkdir. Jeder Verzeichnisname besteht aus einem Präfix (einer Zeichenfolge) und einem Index (einer Ganzzahl). Angenommen, ich möchte, dass das Präfix "s" ist und die Indizes im Bereich von 1 bis 50 liegen. Dies bedeutet, dass ich Verzeichnisse mit dem Titel erstellen möchte:

s1,, s2... s49,,s50

Gibt es eine Möglichkeit, dies automatisch mit zu tun mkdir? Vielen Dank für Ihre Zeit.

Andrew
quelle
2
Welche Shell benutzt du?
Francesco Turco
@FrancescoTurco Ich benutze bash. Vielen Dank für Ihre Zeit!
Andrew
3
FYI, finde ich es viel nützliche feste Breite Indizes zu verwenden, wie: s01, s02, ..., s49, s50. Wenn ich Indizes mit fester Breite verwendet habe, wird /bin/lsfast immer die gewünschte Reihenfolge erstellt.
Rob

Antworten:

31

Sie können dies mit einem Shell-Skript tun.

Pure sh - das funktioniert auch auf Pre-POSIX-Bourne-Shells:

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

Wenn Sie eine große Anzahl von Verzeichnissen erstellen möchten, können Sie das Skript beschleunigen, indem Sie es auf einen einzigen Aufruf von reduzieren und mkdirShell-Builtins für Tests und Berechnungen verwenden. So was:

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 oder bash machen dies viel einfacher, aber ich sollte darauf hinweisen, dass dies nicht eingebaut ist mkdirund möglicherweise nicht in anderen Shells funktioniert. In größeren Fällen kann die Anzahl oder Gesamtgröße der Argumente, die an einen Befehl übergeben werden können, begrenzt sein.

mkdir s{1..50}
Random832
quelle
3
+1 Das ist großartig! In einem Punkt muss ich allerdings kurz aufpassen: Wäre n=$(( n + 1 ))genauso streng POSIX gewesen und hätte dich keine Subshell gekostet.
Kojiro
@rahmu das [[Schlüsselwort ist nicht POSIX. (Ganz zu schweigen davon, dass [ ist eine Shell - builtin in vielen modernen Muscheln.)
kojiro
@kojiro: Funktioniert [[auf meinem ksh88(was älter ist bash), also habe ich angenommen, dass es POSIX ist. Ich konnte keine Erwähnung in der POSIX-Spezifikation finden, also glaube ich, dass Sie Recht haben. Danke für die Information!
Rahmu
Ich dachte darüber nach, eine Version mit arithmetischer Erweiterung hinzuzufügen, wollte aber "pure sh" auf Dinge beschränken, die auch für Vorgängerversionen von POSIX funktionieren würden. Aus dem gleichen Grund habe ich auch seq nicht erwähnt - wenn Sie seq haben, haben Sie wahrscheinlich bash. Das Schleifenbeispiel eignet sich auch zum Umgehen von Argumentgrenzwerten für eine größere Anzahl von Verzeichnissen. Dies bedeutet auch, dass for i in {range}für Benutzer fortgeschrittener Shells ein Platz vorhanden ist.
Random832
Der zsh Hinweis am Ende ist unglaublich, es hat mir so viel Zeit gespart!
Jase
33
  • Eins

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

    mkdir s{1..50}

    Diese Option funktioniert in bash , zsh und ksh93

  • Drei

    mkdir $(printf "s%02i " $(seq 1 50))
Jhonathan
quelle
4
Warum würden Sie jemals eins über zwei verwenden?
Kevin
7
Sie möchten vielleicht mehr $ials nur ein Verzeichnis erstellen, z mkdir s$i ; echo $i > s$i/$i. Außerdem ist One ein schönes, einfaches Beispiel für die Verwendung einer for-Schleife in bash ... auf einer Site wie dieser ist es keineswegs unwahrscheinlich, dass ein Anfänger sie sieht und denkt: "Nett, ich habe nicht bemerkt, dass Sie das können "---> Erleuchtung.
cas
1
@rahmu Es ist eine Funktion in Bash / Zsh (wahrscheinlich auch ksh93). Sie müssen nicht abstimmen.
Helpermethod
3
@rahmu: Ich denke, man sollte nur überlegen, ob die Antwort von jhonathan das Problem mit der OP-Shell (bash) behebt, nicht unbedingt mit anderen.
Francesco Turco
4
@ Kevin, obwohl es wahrscheinlich kein Problem für fünfzig ist, wenn Sie fünfhundert Verzeichnisse haben, um sich Gedanken über Argumentgrenzen zu machen.
Random832
10

Viele komplizierte Antworten hier, aber Bash macht es wirklich einfach. Sicher, die reine POSIX-Lösung funktioniert, aber warum nicht trotzdem die von bashIhnen verwendete Shell nutzen? Sie können dies leicht mit Klammer Expansion :

% 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
quelle
5

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

oder wenn Sie mit Nullen aufgefüllte Zahlen haben möchten (was für die Sortierung besser wäre):

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

oder:

mkdir s$(seq -s ' s' -w 1 50)- beachte den String 's' kurz vor dem $(), ohne diesen wird als erstes Verzeichnis nur '01' anstatt 's01' angelegt

und schlussendlich: mkdir $(printf "s%02i " $(seq 1 50))

seq ist von GNU Coreutils

seltsamerweise erlaubt seqs --formatoder -foption nur die Gleitkomma-Doppeltypen von printf (wie f und g. auch ein seltsames Fließkomma-Hex-Format, für das ich nie eine Verwendung gefunden habe). Ich habe keine Idee warum. Es wäre schön, wenn es auch andere printf(3)numerische Typen wie Integer (d, i), Octal (o, U) oder Hex (x, X) unterstützen würde.

Wie auch immer, ein Doppelformat mit einer Dezimalgenauigkeit von 0 entspricht einer Ganzzahl %.0foder %02.0fliegt nahe genug für diesen Zweck.

$ seq --help
Verwendung: seq [OPTION] ... LAST
  oder: seq [OPTION] ... ZUERST
  oder: seq [OPTION] ... ERSTES ERHÖHEN LETZT
Drucken Sie die Nummern in Schritten von INKREMENT von ERST bis LETZT.

  -f, --format = FORMAT verwende Gleitkomma-FORMAT im Printf-Stil
  -s, --separator = STRING trenne Zahlen mit STRING (Standard: \ n)
  -w, --equal-width gleicht die Breite durch Auffüllen mit führenden Nullen aus
      --help Diese Hilfe anzeigen und beenden
      --version gibt Versionsinformationen aus und beendet sich

Wenn FIRST oder INCREMENT weggelassen wird, ist der Standardwert 1. Das heißt, ein
Ohne INCREMENT ist der Standardwert 1, auch wenn LAST kleiner als FIRST ist.
FIRST, INCREMENT und LAST werden als Gleitkommawerte interpretiert.
INCREMENT ist normalerweise positiv, wenn FIRST kleiner als LAST ist, und
INCREMENT ist normalerweise negativ, wenn FIRST größer als LAST ist.
FORMAT muss zum Drucken eines Arguments vom Typ double geeignet sein.
Der Standardwert ist% .PRECf, wenn FIRST, INCREMENT und LAST alle Festpunkte sind
Dezimalzahlen mit höchster Präzision PREC und ansonsten% g.

Siehe auch: http://www.gnu.org/software/coreutils/manual/html_node/seq-invocation.html

cas
quelle
{1,50}oder {01,50}(zum Null-Auffüllen) ist viel einfacher und verständlicher.
Kevin
1
wahr ... wenn du bash anstatt sh verwendest. Deshalb habe ich @ Random832's Antwort upvoted. Das ist eine gute Antwort. Die Verwendung von seq ist auch eine nützliche Antwort.
cas
4

Nur um anders zu sein, hier ist eine POSIX-sh-Lösung, die Rekursion verwendet:

makedirs() {
  [ "$1" -gt 0 ] || return
  mkdir "s$1"
  makedirs $(( $1 - 1 ))
}
$ makedirs 9
$ ls
s1  s2  s3  s4  s5  s6  s7  s8  s9
Kojiro
quelle