Comment créer un répertoire dans tous les sous-répertoires?

34

Supposons que j'ai une structure de répertoire comme celle-ci:

$ [~ / practice] ls
a B c d/

Maintenant, je veux créer un répertoire tmp1dans tous les sous-répertoires de practiceet je fais ceci:

$ [~ / practice] mkdir * / tmp1
mkdir: impossible de créer le répertoire `* / tmp1 ': aucun fichier ou répertoire de ce type

Puis j'essaie le -pcommutateur et je finis avec un répertoire nommé *avec un sous-répertoiretmp1

$ [~ / practice] mkdir -p * / tmp1

$ [~ / practice] ls
*/ a B c d/

Je sais que l'utilisation de -pswitch est de créer plusieurs répertoires inexistants. J'ai juste pensé que cela pourrait aider.

Comment créer tmp1simultanément dans tous les sous-répertoires?

Si cela peut être fait, comment puis-je l' étends à créer \tmp1, \tmp2, \tmp3dans \a, \bet \cà la fois?

Edit: J'ai manqué de mentionner que les répertoires ne doivent pas être simples et dans l' ordre, comme a, b, cetc., et le répertoire à créer est pas nécessairement comme tmp1, tmp2.

$ [~ / practice] ls
chien / chat / rat /

En eux, je voudrais avoir quelque chose comme

$ [~ / pratique] ls *
chien:
rouge Bleu/

chat:
rouge Bleu/

rat:
rouge Bleu/
Animesh
la source
1
Compte tenu de la réponse de Christopher , vous devez préciser si "create \ tmp1, \ tmp2, \ tmp3 dans \ a, \ b et \ c" doit résulter en un total de 3 ou 9 sous-répertoires.
Manatwork
@manatwork: C'est un bon point. Il devrait créer 9 sous-répertoires.
Animesh
C'est mon aide pour résoudre le problème d'espace dans le nom du répertoire sudo find ./ -depth -type d -exec echo '"{} / RCS"' \;

Réponses:

44

Avec globs :

for dir in */; do mkdir -- "$dir/tmp1"; done

REMARQUE

  • Je traite seulement dirs (y compris des liens symboliques vers dirs) avec le petit hack d'utiliser */comme glob
  • Si vous souhaitez créer plusieurs sous-répertoires à la fois:

    for dir in */; do mkdir -- "$dir"/{tmp1,foo,bar,qux}; done

Gilles Quenot
la source
Puis-je faire for i in */; do mkdir "$i/itemone" "$i/itemtwo"; donepour plusieurs noms de répertoires non-en ordre?
Animesh
J'ai testé cela et c'est très possible. Merci.
Animesh
Voir mon article publié
Gilles Quenot le
1
Le développement d'accolades n'est pas effectué dans la chaîne entre guillemets.
Manatwork
Oui, merci, article édité par Stéphane Chazelas en conséquence ...
Gilles Quenot
10

[...] comment puis-je l'étendre pour créer \ tmp1, \ tmp2, \ tmp3 dans \ a, \ b et \ c à la fois?

 mkdir {a,b,c}/tmp{1,2,3}
Christopher
la source
10

Avec GNU ou BSD *, trouvez:

find -mindepth 1 -maxdepth 1 -type d -exec mkdir {}/newdir \;

ou en utilisant l'expansion de paramètre:

dirs=(*/)
mkdir -- "${dirs[@]/%/newdir}"

* Comprend OS X

kojiro
la source
2
Avec la syntaxe de recherche standard:find . -name . -o -prune -type d -exec sh -c 'exec mkdir "$1/newdir"' sh {} \;
Stéphane Chazelas le
1
Notez également les différences entre les deux solutions: la première inclut les répertoires cachés, la seconde ajoute un newdir dans les répertoires liés par un lien symbolique quelconque dans le répertoire actuel.
Stéphane Chazelas
6

Hors sujet puisque vous mentionnez bash, mais pour l'enregistrement, avec zsh, vous feriez:

dirs=(*(/))
mkdir -- $^dirs/tmp1

$^varactive l’ expansion de type accolade pour l’extension du tableau. Cela rappelle rcl' ^opérateur de et dans rc(ou son dérivé es), vous l'écriviez:

dirs=(*/)
mkdir -- $dirs^tmp1

Cependant, notez (et il en va de même pour les solutions bash données ici) que, dans la solution rc, dirscontiendrait également des liens symboliques vers des répertoires. Dans la solution zsh, remplacez *(/)par *(-/)si vous souhaitez inclure des liens symboliques vers des répertoires.

Stéphane Chazelas
la source
+1 pour votre point sur les liens symboliques! Ce problème peut être souhaité, mais la plainte de mkdir concernant la création d'un répertoire en double peut être supprimée avec l' -pindicateur.
Kojiro
4

Portable, passez en boucle sur les répertoires parents:

for d in */; do mkdir "$d/red" "$d/blue"; done

Ajoutez --après mkdirsi vous pouvez avoir des répertoires dont le nom commence par -.

En zsh, vous pouvez le faire en une seule commande avec le e qualificatif glob :

mkdir *(/e\''REPLY=($REPLY/{red,blue})'\')

mais il est plus rapide de taper ceci comme deux commandes:

d=(*(/)); mkdir $^d/{red,blue}
Gilles, arrête de faire le mal
la source
1
Sur un site qui est censé être une référence, je dirais plutôt " mkdir -- whateveret omettez -- si vous avez l'intention d'élargir ce qui pourrait éventuellement être pris comme options de la mkdircommande.". Il ne sert à rien d'omettre --ici. Ce n'est peut-être pas un problème dans le cas du PO, mais c'est un problème dans le cas général. Je pense que nous avons le devoir d'enseigner la syntaxe correcte et sûre ici.
Stéphane Chazelas
@StephaneChazelas Dans un contexte de script, je mets toujours tout le nécessaire, --ainsi que des citations et des gros avertissements lorsque les nouvelles lignes ne sont pas prises en charge. Dans un contexte de ligne de commande, je préfère montrer la version rapide qui fonctionne dans la pratique d’abord, et la version pare-balles en complément.
Gilles 'SO- arrête d'être méchant'
1

Vous pouvez faire ça comme ça:

mkdir {a,b,c,d}/tmp1
ДМИТРИЙ МАЛИКОВ
la source
1
Et s'il a 100 annuaires?
Bernhard
1

Variation sur la réponse de sputnick qui évite les fichiers autres que des répertoires:

for x in *; do if [ -d "$x" ]; then mkdir "$x/tmp1"; fi; done
boucle d'or
la source
Je ne traite que les dir, c'est toute la magie ...
Gilles Quenot
cool, j'ai compris;)
goldilocks
2
Cela ne devrait pas être if [ -d "$x" ];…?
Kojiro
Oui. Je n'ai pratiquement jamais d'espaces dans les noms de fichiers et j'ai tendance à les oublier ...
goldilocks
1

C’est un bon exemple de l’ancien maître Unix (testé sur FreeBSD 10.1) si vous voulez contrôler la version (avec l’archivage RCS verrouillé: ci -l avec un bref commentaire comme ir: pour la version initiale) vos fichiers de configuration / etc / * sur ~ / .his / etc

sudo rsync -av /etc/ ~/.his
sudo find -d ~/.his/etc -type d -exec echo '{}/RCS' \; | xargs sudo mkdir -p
sudo find -d ~/.his/etc \! -name "RCS" | xargs sudo ci -l -mir -t-ir
utilisateur108341
la source
Je ne vois pas comment cela répondrait au PO
Archemar
1

Devrait être \! nom "RCS" et cela fonctionne mieux lors de la première vérification.

sudo trouve ~ / .his / etc \! -name "RCS" -ls

sudo trouve -d ~ / .his / etc \! -name "RCS" | xargs sudo ci -l -mir -t-ir

Ce dernier fonctionne également très bien pour le filtre en partie filtrant tout le contenu RCS sur le nom du fichier:

sudo trouve -d ~ / .his / etc -type f | grep -v RCS | xargs sudo ci -l -mir -t-ir

utilisateur108341
la source
1

c'est une aide précieuse pour moi. J'avais besoin de créer un ensemble de sous-répertoires dans plusieurs dossiers et quelque chose comme:

!/bin/sh

cd /dest/cont

for dir in */*/; do
    mkdir -p -- $dir/{FB,Video,Audio,proj};
done

a bien fonctionné sauf lorsqu'un espace blanc est rencontré. Est-il possible d'ignorer les espaces dans la */*/partie des arguments?

johno
la source