Usando la expansión de parámetros para generar la lista de argumentos para `mkdir -p`

10

Tengo algo como esto:

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

Quiero crear un directorio bardebajo de cada uno de los subdirectorios debajo foo.

Si trato de hacer esto con

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

... me sale el error

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

(En retrospectiva, puedo entender la razón del error).

Sé que puedo resolver el problema original con un bucle for, pero tengo curiosidad por saber si zshadmite alguna forma de expansión de parámetros que produzca el argumento deseado para una sola invocación de mkdir -p. IOW, una expansión de parámetro equivalente a "agregar /bara cada prefijo generado al expandir /tmp/foo/*", lo que resulta en

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

Respuestas:

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

Este es un globing extendido que tiene un qindicador de glob uiet que usa un calificador glob para hacer coincidir solo directorios y un modificador para realizar una ssustitución (usando el %carácter de patrón que solo está disponible en el modo de patrón de sustitución del historial ) que agrega una cadena a cada palabra.

man zshexpn
JdeBP
fuente
Wow estoy impresionado. Incluso lo encontré todo en la página de manual que especifique.
Comodín el
1
Tenga en cuenta que el póster original especificado mkdir -p, que tendría un efecto ligeramente diferente de su comando de no arrojar errores si algunos de esos directorios ya tienen barsubdirectorios. Punto menor pero vale la pena señalar aquí. :)
Comodín el
1
Otra forma es usar la expansión de matriz a través de ${^spec}y agregar bara cada elemento de lo que se /tmp/foo/*(/)expande a: set -- /tmp/foo/*(/)luegomkdir -p -- "${^@}/bar"
don_crissti
5

Claro, usa un bucle

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

los globos se utilizan para expandir listas de elementos existentes , no cosas que aún no se han creado.

Thomas Dickey
fuente
Lo siento, me temo que mi pregunta no fue formulada claramente. Lo aclararé.
kjo
2
Esto no responde si zshpuede expandir los globos y agregar texto con una sintaxis única, pero creo que es la única forma de hacer lo que quiere, @kjo.
Comodín el
4

Si los directorios están en una matriz, puede usar la ${^...}forma de expansión.

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

Puedes usar findy xargspara hacerlo:

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

que utiliza -maxdepth 1y -mindepth 1para evitar la creación baren subdirectorios de objetivos, y en /tmp/foosí mismo respectivamente. type dlo hace considerar solo directorios.

Debe eliminar echopara realizar acciones reales, de lo contrario echosolo imprimirá líneas para ejecutar. También puede encerrarlo en sustitución $()para ejecutarlo.

Manual dice que xargs -ies obsoleto, pero no he encontrado ninguna otra alternativa igualmente útil, por lo que debe todavía trabajo por algunos años ... Se puede reemplazar -icon -I'{}'a estar al día con eso.

loa_in_
fuente
Esta respuesta y la siguiente me parecen bien. ¿Alguien puede explicar por qué deberían ser rechazados? Los votos negativos están bien, pero ¿cómo podemos saber si no se dan razones?
Joe
Es una alternativa de trabajo que no hace más que lo que OP pidió. Me gana
loa_in_
Creo que es una especie de sesgo que las respuestas deben tener malas respuestas, por lo que los prejuicios afectaron mi reputación.
loa_in_
No me gustan los votos negativos inexplicables, pero no he visto tal sesgo. Por lo general, las respuestas "malas" (las que entiendo) son realmente malas.
Joe
0

@loa_in_ tenía la mayor parte, pero la findsalida de la tubería tiende a ser un paso en falso.

find /tmp/foo -maxdepth 1 -mindepth 1 -type d -exec mkdir {}/bar \;
Sammitch
fuente
Solo lo uso xargscon diferentes herramientas que no tienen -execalternativa, así que uso mi enfoque, ya que funciona con todas ellas por igual.
loa_in_