¿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/

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


¿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}

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


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.


¡+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}

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

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

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

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


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?

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.