Utilisation de l'expansion des paramètres pour générer une liste d'arguments pour `mkdir -p`

10

J'ai quelque chose comme ça:

% ls -1dF /tmp/foo/*
/tmp/foo/000f9e956feab3ee4625aebb65ae7bae9533cdbc/
/tmp/foo/002e34c2218f2c86fefd2876f0e5c2559c5fb3c4/
/tmp/foo/00b483576791bab751e6cb7ee0a7143af43a8069/
.
.
.
/tmp/foo/fedd0f7b545e7ae9600142656756456bc16874d3/
/tmp/foo/ff51ac87609012137cfcb02f36624f81cdc10788/
/tmp/foo/ff8b983a7411395344cad64182cb17e7cdefa55e/

Je veux créer un répertoire barsous chacun des sous-répertoires sous foo.

Si j'essaye de faire ça avec

% mkdir -p /tmp/foo/*/bar

... je reçois l'erreur

zsh: no matches found: /tmp/foo/*/bar

(Avec le recul, je peux comprendre la raison de l'erreur.)

Je sais que je peux résoudre le problème d'origine avec une boucle for, mais je suis curieux de savoir s'il zshprend en charge une certaine forme d'expansion de paramètres qui produirait l'argument souhaité pour une seule invocation de mkdir -p. IOW, une extension de paramètre équivalente à "ajouter /barà chaque préfixe généré par l'expansion /tmp/foo/*", résultant en

% mkdir -p /tmp/foo/000f9e956feab3ee4625aebb65ae7bae9533cdbc/bar ... /tmp/foo/ff8b983a7411395344cad64182cb17e7cdefa55e/bar
kjo
la source

Réponses:

13
setopt histsubstpattern extendedglob
mkdir -p /tmp/foo/*(#q/:s_%_/bar_)

Il s'agit d' un globbing étendu doté d'un qindicateur de glob uiet qui utilise un qualificateur glob pour correspondre uniquement aux répertoires et un modificateur pour effectuer une ssubstitution (en utilisant le %caractère de modèle qui n'est disponible qu'en mode de modèle de substitution d'historique ) qui ajoute une chaîne à chaque mot.

man zshexpn
JdeBP
la source
Wow je suis impressionné. J'ai même tout trouvé dans la page de manuel que vous spécifiez.
Wildcard
1
Notez que l'affiche originale spécifiée mkdir -p, ce qui aurait l'effet légèrement différent de votre commande de ne pas lancer d'erreurs si certains de ces répertoires ont déjà des barsous - répertoires. Point mineur mais à noter ici. :)
Wildcard
1
Une autre façon consiste à utiliser l'extension de tableau via ${^spec}et à ajouter barà chaque élément de ce qui se /tmp/foo/*(/)développe pour: set -- /tmp/foo/*(/)ensuitemkdir -p -- "${^@}/bar"
don_crissti
5

Bien sûr - utilisez une boucle

for n in /tmp/foo/*; do mkdir "$n/bar";done

les globes sont utilisés pour développer des listes d' éléments existants , pas des choses qui n'ont pas encore été créées.

Thomas Dickey
la source
Désolé, je crains que ma question n'ait pas été clairement formulée. Je vais le clarifier.
kjo
2
Cela ne répond pas si vous zshpouvez développer des globes et ajouter du texte avec une seule syntaxe, mais je pense que c'est probablement la seule façon de faire ce que vous voulez, @kjo.
Wildcard
4

Si les répertoires sont dans un tableau, vous pouvez utiliser la ${^...}forme d'extension.

a=(/tmp/foo/*/)
mkdir -p ${^a}bar
chepner
la source
0

Vous pouvez utiliser findet xargspour le faire:

find /tmp/foo -maxdepth 1 -mindepth 1 -type d | xargs -i echo mkdir -p {}/bar

qui utilise -maxdepth 1et -mindepth 1pour empêcher la création de barsous-répertoires de cibles, et en /tmp/foosoi respectivement. type dle fait considérer uniquement les répertoires.

Vous devez supprimer echopour effectuer des actions réelles, sinon vous echon'imprimerez que les lignes à exécuter. Vous pouvez également le placer en substitution comme $()pour l'exécuter.

Le manuel dit qu'il xargs -iest obsolète, mais je n'ai trouvé aucune autre alternative tout aussi pratique, donc cela devrait encore fonctionner pendant quelques années ... Vous pouvez remplacer -ipar -I'{}'pour être à jour avec cela.

loa_in_
la source
Cette réponse et la suivante me semblent bonnes. Quelqu'un peut-il expliquer pourquoi il faudrait voter contre? Les votes négatifs sont bons, mais comment pouvons-nous savoir si aucune raison n’est donnée?
Joe
C'est une alternative qui ne fait rien d'autre que ce que OP a demandé. Me bat.
loa_in_
Je pense que c'est une sorte de parti pris que les réponses doivent avoir de mauvaises réponses, donc les préjugés ont nui à ma réputation.
loa_in_
Je n'aime pas les votes bas inexpliqués, mais je n'ai pas vu un tel parti pris. Habituellement, les «mauvaises» réponses (celles que je comprends) sont en fait mauvaises.
Joe
0

@loa_in_ en avait la plupart, mais la findsortie de la tuyauterie a tendance à être un faux pas.

find /tmp/foo -maxdepth 1 -mindepth 1 -type d -exec mkdir {}/bar \;
Sammitch
la source
Je l'utilise simplement xargsavec différents outils qui n'ont pas d' -execalternative, donc j'utilise mon approche car elle fonctionne avec tous également.
loa_in_