Creazione di numerose directory usando mkdir


14

Vorrei creare molte directory usando mkdir. Ciascun nome di directory sarà composto da un prefisso (una stringa) e un indice (un numero intero). Supponiamo che vorrei che il prefisso fosse "s" e che gli indici fossero compresi tra 1 e 50. Ciò significa che vorrei creare directory intitolate:

s1,, s2... s49,,s50

C'è un modo per farlo automaticamente usando mkdir? Grazie per il tuo tempo.


2
Quale shell stai usando?
Francesco Turco,

@FrancescoTurco che sto usando bash. Grazie per il tuo tempo!
Andrew,

3
Cordiali saluti, lo trovo molto più utile da usare indici a larghezza fissa, come: s01, s02, ..., s49, s50. Se ho usato indici a larghezza fissa, /bin/lsquasi sempre produce l'ordine che desidero.
Rob,

Risposte:


32

Puoi farlo con uno script di shell.

Pure sh - funzionerà anche con shell bourne pre-POSIX:

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

Se si desidera creare un numero elevato di directory, è possibile rendere più veloce lo script riducendolo a una singola chiamata mkdire utilizzando i comandi incorporati della shell per i test e l'aritmetica. Come questo:

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 o bash lo rendono molto più semplice, ma dovrei sottolineare che non è integrato mkdire potrebbe non funzionare in altre shell. Per casi più grandi, potrebbe anche essere influenzato da limiti sul numero o sulla dimensione totale degli argomenti che possono essere passati a un comando.

mkdir s{1..50}

3
+1 Questo è fantastico! Devo fare una chiacchierata su una cosa, però: n=$(( n + 1 ))sarebbe stato altrettanto rigorosamente POSIX e non ti sarebbe costato una subshell.
Kojiro,

@rahmu la [[parola chiave non è POSIX. (Per non parlare del fatto che [ è una shell integrata in molte conchiglie moderne.)
Kojiro,

@kojiro: [[funziona sul mio ksh88(che precede bash) quindi ho pensato che fosse POSIX. Non ho trovato alcuna menzione nelle specifiche POSIX, quindi credo che tu abbia ragione. Grazie per le informazioni!
Rahmu,

Ho pensato di aggiungere una versione usando l'espansione aritmetica, ma volevo limitare "sh puro" a cose che avrebbero funzionato anche su versioni pre-POSIX. Inoltre non ho menzionato seq per lo stesso motivo: se hai seq probabilmente hai bash. L'esempio del ciclo è anche utile per aggirare i limiti degli argomenti per un numero maggiore di directory, il che significa anche che c'è posto for i in {range}per gli utenti di shell avanzate.
Casuale 832,

Il suggerimento zsh alla fine è sorprendente, mi ha fatto risparmiare così tanto tempo!
Jase,

33
  • Uno

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

    mkdir s{1..50}

    Questa opzione funziona in bash , zsh e ksh93

  • Tre

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

4
Perché mai ne useresti uno su due?
Kevin,

7
potresti voler fare di più con una $isemplice directory, ad es mkdir s$i ; echo $i > s$i/$i. Inoltre, One è un bell'esempio semplice di utilizzo di un ciclo for in bash ... su un sito come questo non è affatto improbabile per un utente inesperto vederlo e pensare "bello, non mi rendevo conto che potevi farlo "---> illuminazione.
Cas

1
@rahmu È una funzionalità trovata in Bash / Zsh (probabilmente anche ksh93). Non è necessario effettuare il downgrade.
helpermethod,

3
@rahmu: Penso che si dovrebbe considerare solo se la risposta di jhonathan risolve il problema con la shell dell'OP (bash), non necessariamente con gli altri.
Francesco Turco,

4
@Kevin mentre non è probabile che sia un problema per cinquanta, se hai cinquecento directory da farti potresti preoccuparti dei limiti degli argomenti.
Casuale 832,

10

Molte risposte complicate qui, ma bash lo rende davvero facile. Certo, la soluzione POSIX pura funziona, ma perché non sfruttare la bashshell che stai usando, comunque? Puoi farlo facilmente con l' espansione del controvento :

% 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

5

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

o se vuoi numeri a zero (che sarebbe meglio per l'ordinamento):

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

o:

mkdir s$(seq -s ' s' -w 1 50)- nota la stringa 's' appena prima di $(), senza di essa la prima directory creata sarà solo '01' anziché 's01'

e infine: mkdir $(printf "s%02i " $(seq 1 50))

seq è di GNU Coreutils

stranamente, seq --formato l' -fopzione consentono solo i doppi tipi in virgola mobile di printf (come f e g. anche uno strano formato esadecimale in virgola mobile che non ho mai trovato utile). Non ho idea del perché. Sarebbe bello se supportasse anche altri printf(3)tipi numerici come intero (d, i), ottale (o, U) o esadecimale (x, X).

Ad ogni modo, un doppio formato con precisione decimale 0 gradisce %.0fo %02.0fè abbastanza vicino a un numero intero per questo scopo.

$ seq --help
Utilizzo: seq [OPTION] ... LAST
  oppure: seq [OPZIONE] ... PRIMA ULTIMA
  oppure: seq [OPZIONE] ... PRIMO INCREMENTO ULTIMO
Stampa i numeri da FIRST a LAST, con incrementi di INCREMENT.

  -f, --format = FORMAT usa FORMAT a virgola mobile in stile printf
  -s, --separator = STRING usa STRING per separare i numeri (impostazione predefinita: \ n)
  -w, --equal-width equalizza la larghezza mediante riempimento con zeri iniziali
      --help visualizza questa guida ed esce
      --version informazioni sulla versione di output ed esce

Se si omette FIRST o INCREMENT, il valore predefinito è 1. Cioè, an
omesso INCREMENT predefinito è 1 anche quando LAST è più piccolo di FIRST.
FIRST, INCREMENT e LAST sono interpretati come valori in virgola mobile.
L'INCREMENTO è generalmente positivo se FIRST è inferiore a LAST e
L'INCREMENTO è generalmente negativo se FIRST è maggiore di LAST.
FORMATO deve essere adatto per la stampa di un argomento di tipo `doppio ';
il valore predefinito è% .PRECf se FIRST, INCREMENT e LAST sono tutti a virgola fissa
numeri decimali con la massima precisione PREC e in% g altrimenti.

Vedi anche: http://www.gnu.org/software/coreutils/manual/html_node/seq-invocation.html


{1,50}oppure {01,50}(per zero-padding) è molto più semplice e comprensibile.
Kevin,

1
vero ... se stai usando bash anziché sh. ecco perché ho votato a favore della risposta di @ Random832. è una buona risposta. anche usare seq è una risposta utile.
Cas

4

Solo per essere diversi, ecco una soluzione sh POSIX che utilizza la ricorsione:

makedirs() {
  [ "$1" -gt 0 ] || return
  mkdir "s$1"
  makedirs $(( $1 - 1 ))
}
$ makedirs 9
$ ls
s1  s2  s3  s4  s5  s6  s7  s8  s9
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.