Création de nombreux répertoires à l'aide de mkdir

14

Je voudrais créer de nombreux répertoires en utilisant mkdir. Chaque nom de répertoire sera composé d'un préfixe (une chaîne) et d'un index (un entier). Supposons que je souhaite que le préfixe soit "s" et que les indices soient compris entre 1 et 50. Cela signifie que je voudrais créer des répertoires intitulés:

s1,, s2... s49,,s50

Existe-t-il un moyen de le faire automatiquement en utilisant mkdir? Merci pour votre temps.

Andrew
la source
2
Quel shell utilisez-vous?
Francesco Turco
@FrancescoTurco que j'utilise bash. Merci pour votre temps!
Andrew
3
Pour votre information, je trouve qu'il est beaucoup plus utile d'utiliser des indices de largeur fixe, comme: s01, s02, ..., s49, s50. Si j'ai utilisé des indices à largeur fixe, /bin/lsproduit presque toujours l'ordre que je veux.
Rob

Réponses:

32

Vous pouvez le faire avec un script shell.

Pure sh - cela fonctionnera même sur les coques bourne pré-POSIX:

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

Si vous souhaitez créer un grand nombre de répertoires, vous pouvez rendre le script plus rapide en le réduisant à un seul appel mkdirou en utilisant des commandes internes de shell pour les tests et l'arithmétique. Comme ça:

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 ou bash rendent cela beaucoup plus facile, mais je dois souligner que cela n'est pas intégré mkdiret peut ne pas fonctionner dans d'autres shells. Pour les cas plus importants, il peut également être affecté par des limites sur le nombre ou la taille totale des arguments qui peuvent être passés à une commande.

mkdir s{1..50}
Aléatoire832
la source
3
+1 C'est super! Je dois dire une chose, cependant: n=$(( n + 1 ))aurait été tout aussi strictement POSIX et ne vous coûterait pas un sous-shell.
kojiro
@rahmu le [[mot-clé n'est pas POSIX. (Sans oublier qu'il [ s'agit d' un obus intégré à de nombreux obus modernes.)
kojiro
@kojiro: [[fonctionne sur mon ksh88(qui est antérieur bash) donc j'ai supposé que c'était POSIX. Je n'ai trouvé aucune mention de cela dans la spécification POSIX, donc je pense que vous avez raison. Merci pour l'info!
rahmu
J'ai pensé à ajouter une version utilisant l'expansion arithmétique, mais je voulais limiter "pure sh" aux choses qui auraient également fonctionné sur les versions pré-POSIX. Je n'ai pas non plus mentionné le seq pour la même raison - si vous avez un seq, vous avez probablement bash. L'exemple de boucle est également bon pour contourner les limites d'argument pour un plus grand nombre de répertoires, ce qui signifie également qu'il y a une place for i in {range}pour les utilisateurs de shells avancés.
Random832
L'indice zsh à la fin est incroyable, cela m'a fait gagner beaucoup de temps!
Jase
33
  • Un

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

    mkdir s{1..50}

    Cette option fonctionne en bash , zsh et ksh93

  • Trois

    mkdir $(printf "s%02i " $(seq 1 50))
Jhonathan
la source
4
Pourquoi en utiliseriez-vous un sur deux?
Kevin
7
vous voudrez peut-être faire plus $ique simplement créer un répertoire, par exemple mkdir s$i ; echo $i > s$i/$i. De plus, One est un bel exemple simple d'utilisation d'une boucle for dans bash ... sur un site comme celui-ci, il n'est pas du tout improbable pour un utilisateur novice de le voir et de penser "bien, je ne savais pas que vous pouviez faire ça "---> l'illumination.
cas
1
@rahmu C'est une fonctionnalité trouvée dans Bash / Zsh (probablement aussi ksh93). Pas besoin de downvote.
helpermethod
3
@rahmu: Je pense que l'on ne devrait considérer que si la réponse de jhonathan résout le problème avec le shell de l'OP (bash), pas nécessairement avec les autres.
Francesco Turco
4
@Kevin alors que ce n'est probablement pas un problème pour cinquante, si vous avez cinq cents répertoires à créer, vous pourriez vous inquiéter des limites d'argument.
Random832
10

Beaucoup de réponses compliquées ici, mais bash le rend vraiment facile. Bien sûr, la solution POSIX pure fonctionne, mais pourquoi ne pas profiter du bashshell que vous utilisez, de toute façon? Vous pouvez le faire facilement avec l' extension d'accolade :

% 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
abat-jour
la source
5

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

ou si vous voulez des nombres remplis par zéro (ce qui serait mieux pour le tri):

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

ou:

mkdir s$(seq -s ' s' -w 1 50)- notez la chaîne 's' juste avant le $(), sans elle le premier répertoire créé sera juste '01' plutôt que 's01'

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

seq est de GNU Coreutils

bizarrement, seq --formatou -foption n'autorise que les doubles types à virgule flottante de printf (comme f et g. également un étrange format hexadécimal à virgule flottante pour lequel je n'ai jamais trouvé d'utilisation). Je ne sais pas pourquoi. Ce serait bien s'il supportait également d'autres printf(3)types numériques comme entier (d, i), octal (o, U) ou hex (x, X).

Quoi qu'il en soit, un format double avec une précision décimale 0 comme %.0fou %02.0fest assez proche d'un entier à cet effet.

$ seq --help
Utilisation: seq [OPTION] ... LAST
  ou: seq [OPTION] ... PREMIER DERNIER
  ou: seq [OPTION] ... PREMIÈRE AUGMENTATION DERNIÈRE
Imprimez les nombres du PREMIER au DERNIER, par étapes d'AUGMENTATION.

  -f, --format = FORMAT utilise le format à virgule flottante du style printf
  -s, --separator = STRING utilise STRING pour séparer les nombres (par défaut: \ n)
  -w, --equal-width égalise la largeur par un remplissage avec des zéros non significatifs
      --help afficher cette aide et quitter
      --version afficher les informations de version et quitter

Si FIRST ou INCREMENT est omis, sa valeur par défaut est 1. Autrement dit, un
omis INCREMENT par défaut à 1 même lorsque LAST est plus petit que FIRST.
FIRST, INCREMENT et LAST sont interprétés comme des valeurs à virgule flottante.
L'AUGMENTATION est généralement positive si PREMIER est plus petit que DERNIER, et
L'AUGMENTATION est généralement négative si PREMIER est supérieur à DERNIER.
FORMAT doit être adapté à l'impression d'un argument de type "double";
il est par défaut% .PRECf si FIRST, INCREMENT et LAST sont tous des points fixes
nombres décimaux avec une précision maximale PREC, et à% g sinon.

Voir également: http://www.gnu.org/software/coreutils/manual/html_node/seq-invocation.html

cas
la source
{1,50}ou {01,50}(pour le remplissage nul) est beaucoup plus facile et plus compréhensible.
Kevin
1
vrai ... si vous utilisez bash plutôt que sh. c'est pourquoi j'ai voté pour la réponse de @ Random832. c'est une bonne réponse. l'utilisation de seq est également une réponse utile.
cas
4

Juste pour être différent, voici une solution POSIX sh qui utilise la récursivité:

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