¿Cómo se crea un directorio en todos los subdirectorios?

34

Supongamos que tengo una estructura de directorios como esto:

$ [~ / Práctica ls]
a B C D/

Ahora quiero crear un directorio tmp1de todos los subdirectorios de practicey hago esto:

$ [~ / Práctica] * mkdir / tmp1
mkdir: no se puede crear el directorio `* / tmp1' : No existe el fichero o directorio

Entonces trato del -pinterruptor y me EndUp con un directorio llamado *con un subdirectoriotmp1

$ [~ / Práctica] mkdir -p * / tmp1

$ [~ / Práctica ls]
*/ a B C D/

Sé que el uso del -pinterruptor es crear varios directorios inexistentes. Sólo pensé que podría ayudar.

¿Cómo se crea tmp1en todos los subdirectorios a la vez?

Si esto puede hacerse, ¿cómo lo extiendo a crear \tmp1, \tmp2, \tmp3en \a, \by \ca la vez?

Editar: echaba de menos mencionar que los directorios no tienen que ser simples y con el fin, como a, b, cetc., y el directorio que se cree no es necesariamente igual tmp1, tmp2.

$ [~ / Práctica ls]
perro / gato / rata /

En ellos, me gustaría tener algo como

$ [~ / practica] ls *
perro:
rojo azul/

gato:
rojo azul/

rata:
rojo azul/
Animesh
fuente
1
Dada la respuesta de Christopher , debe aclarar si "crear \ tmp1, \ tmp2, \ tmp3 en \ a, \ by \ c" debería dar como resultado un total de 3 o 9 subdirectorios.
manatwork
@manatwork: Ese es un buen punto. Debería crear 9 subdirectorios.
Animesh
Esta es mi ayuda para resolver el problema de espacio en el nombre del directorio sudo find ./ -depth -type d -exec echo '"{} / RCS"' \;

Respuestas:

44

Con globos :

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

NOTA

  • Trato solo los directorios (incluidos los enlaces simbólicos a los directorios) con el pequeño truco de usarlo */como un globo
  • Si desea crear múltiples subdirecciones a la vez:

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

Gilles Quenot
fuente
¿Podría hacerlo for i in */; do mkdir "$i/itemone" "$i/itemtwo"; donepara varios nombres de directorio no ordenados?
Animesh
Probé esto y es muy posible. Gracias.
Animesh
Ver mi publicación editada
Gilles Quenot
1
La expansión de llaves no se realiza en la cadena entre comillas.
manatwork
Sí, gracias, publicación editada por Stephane Chazelas en consecuencia ...
Gilles Quenot
10

[...] ¿cómo lo extiendo para crear \ tmp1, \ tmp2, \ tmp3 en \ a, \ by \ c a la vez?

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

Con GNU o BSD * encuentre:

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

o usando la expansión de parámetros:

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

* Incluye OS X

kojiro
fuente
2
Con sintaxis de búsqueda estándar:find . -name . -o -prune -type d -exec sh -c 'exec mkdir "$1/newdir"' sh {} \;
Stéphane Chazelas
1
También tenga en cuenta las diferencias entre las dos soluciones: la primera incluye directorios ocultos, la segunda agregará un nuevo directorio en los directorios vinculados por cualquier enlace simbólico en el directorio actual.
Stéphane Chazelas
6

Fuera del tema ya que estás mencionando bash, pero para el registro, con zsh, harías:

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

$^varactiva la expansión en forma de llave para la expansión de la matriz. Es una reminiscencia de rc's ^operador y en rc(o su derivado es), que iba a escribir que:

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

Sin embargo, tenga en cuenta (y lo mismo se aplica a las soluciones bash dadas aquí) que en la solución rc dirstambién contendría enlaces simbólicos a directorios. En la solución zsh, cambie *(/)a *(-/)si desea incluir enlaces simbólicos a directorios.

Stéphane Chazelas
fuente
¡+1 por tu punto sobre los enlaces simbólicos! Este comportamiento puede ser deseado, pero la queja de mkdir sobre la creación de un directorio duplicado se puede suprimir con el -pindicador.
kojiro
4

Portablemente, recorra los directorios principales:

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

Agregue --después mkdirsi puede tener directorios cuyo nombre comienza con -.

En zsh, puede hacerlo en un solo comando con el e calificador glob :

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

pero es más rápido escribir esto como dos comandos:

d=(*(/)); mkdir $^d/{red,blue}
Gilles 'SO- deja de ser malvado'
fuente
1
En un sitio que pretende ser una referencia, prefiero decir " mkdir -- whatevery omitir -- si tiene la intención de expandir lo que sea que se tome como opciones para el mkdircomando". No tiene sentido omitir --aquí. Puede que no sea un problema en el caso del OP, pero es uno en el caso general. Creo que tenemos el deber de enseñar la sintaxis correcta y segura aquí.
Stéphane Chazelas
@StephaneChazelas En un contexto de secuencias de comandos, siempre pongo todo lo necesario --y citas y grandes advertencias cuando no se admiten nuevas líneas. En un contexto de línea de comandos, prefiero mostrar la versión rápida que funciona en la práctica primero, y la versión a prueba de balas como complemento.
Gilles 'SO- deja de ser malvado'
1

Puedes hacer eso así:

mkdir {a,b,c,d}/tmp1
ДМИТРИЙ МАЛИКОВ
fuente
1
¿Qué pasa si tiene 100 directorios?
Bernhard
1

Variación en la respuesta de sputnick que evita los archivos que no son de directorio:

for x in *; do if [ -d "$x" ]; then mkdir "$x/tmp1"; fi; done
encerrada dorada
fuente
Trato solo dirs, eso es toda la magia ...
Gilles Quenot
genial, lo tengo;)
Ricitos de Oro
2
¿No debería ser eso if [ -d "$x" ];…?
kojiro
Sí. Prácticamente no tienen espacios en los nombres de archivo y tienden a olvidar esas cosas ...
GOLDILOCKS
1

Este es uno bueno de los antiguos Unix Masters (probado en FreeBSD 10.1) si desea controlar la versión (con el registro RCS bloqueado: ci -l con un breve comentario como ir: para la versión inicial) sus archivos de configuración / etc / * en ~ / .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
usuario108341
fuente
No veo cómo esta respuesta la OP
Archemar
1

Debiera ser \! nombre "RCS" y funciona mejor en el primer registro.

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

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

Este último también funciona muy bien para el cjeck en parte filtrando todo el contenido RCS en el nombre del archivo:

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

usuario108341
fuente
1

Esto es de gran ayuda para mí. Tenía la necesidad de crear un conjunto de subdirectorios en varias carpetas y algo así como:

!/bin/sh

cd /dest/cont

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

funcionó muy bien, excepto cuando se encuentra un espacio en blanco. ¿Hay alguna manera de ignorar espacios en la */*/parte de los argumentos?

johno
fuente