Crea las mismas subcarpetas en otra carpeta

8

Tengo un directorio foocon subdirectorios. Deseo crear los mismos nombres de subdirectorios en otro directorio sin copiar su contenido. ¿Cómo hago esto?

¿Hay alguna manera de obtener lsresultados como una lista de expansión de llaves?

havakok
fuente

Respuestas:

11

Prueba esto,

cd /source/dir/path
find . -type d -exec mkdir -p -- /destination/directory/{} \;
  • . -type d Para enumerar directorios en la ruta actual de forma recursiva.
  • mkdir -p -- /destination/directory/{} crear directorio en el destino.

Esto se basa en una findque admite la expansión {}en el medio de una palabra de argumento.

Siva
fuente
66
Esto puede romperse si cualquier nombre de archivo o carpeta en el nivel superior comienza con un guión. También omite directorios que comienzan con un punto. Finalmente, tenga en cuenta que no todas las implementaciones de findadmiten la interpolación {}en otra cadena.
roaima
1
Y no es muy escalable: tomará mucho tiempo si hay millones de directorios.
Arkadiusz Drabczyk
66
Si hay muchas cosas en /source/dir/path, entonces este puede fallar con una "lista de argumentos demasiado tiempo" cuando los intentos de concha para llamar finda la expansión de *. Es mejor usarlo .allí. Además, la mayoría de las findimplementaciones permiten {}su uso incluso cuando se concatenan con otra cadena, pero no es universal.
Kusalananda
1
Puede usar en .lugar de *en este caso. (El uso de xarg para el rendimiento y la seguridad probablemente requeriría un script externo para la concatenación de ruta)
eckes el
24

Utilizando rsync:

rsync -a --include='*/' --exclude='*' /some/path/dir/ dir

Esto recrearía la estructura de directorios /some/path/dircomo diren el directorio actual, sin copiar ningún archivo.

Cualquier directorio encontrado en la ruta de origen se crearía en el destino debido al patrón de inclusión, pero se excluiría cualquier otra cosa. Como efecto secundario del uso de -a( --archive), obtendrá las mismas marcas de tiempo en todos los subdirectorios en el destino que en la fuente. Esto también funciona para crear estructuras de directorios locales a partir de directorios remotos (y viceversa).

Kusalananda
fuente
¡La respuesta es casi siempre rsync!
Arronical
8

Puede usar findpara recorrer la estructura de origen y llamar mkdira cada directorio que encuentre.

Este ejemplo, usando find, copiará la estructura de su directorio de fooa/tmp/another/

( cd foo && find -type d -exec sh -c 'for d do mkdir -p "/tmp/another/$d"; done' sh {} + )

El execbucle crea el conjunto de directorios debajo foo, que luego se pasa al mkdir. Si no tiene una versión findque comprenda +, puede usarla \;a costa de la eficiencia. Sustitúyalo mkdirpor echo mkdirpara ver qué sucedería sin hacerlo realmente.

roaima
fuente
1
O con el bucle obvio,... -exec sh -c 'for dirpath do mkdir -p "/some/path/$dirpath"; done' sh {} +
Kusalananda
exactamente con GNU find (4.7.0-git) esto no parece funcionar: find: In ‘-exec ... {} +’ the ‘{}’ must appear by itself, but you specified ‘/tmp/another/{}’(aunque sí funciona -exec ... \;)
ilkkachu
Kusalananda, mejora tomada, gracias
roaima
Ilkkachu Estoy seguro de que lo probé, /path/to/{}pero ahora no puedo encontrar ninguna versión donde funcione, así que he adaptado la solución. Gracias
roaima
3

Con el shell bash, puede solicitarle la expansión de cada directorio con la globstaropción:

shopt -s globstar

y luego copie los directorios con un bucle:

for dir in **/
do
  mkdir -p /path/to/dest/"$dir"
done

... o si pensabas que todos encajarían dentro de una llamada para mkdir:

set -- **/
mkdir -- "${@/#//path/to/dest/}"

Esa es la sintaxis de la matriz bash que dice: "tome todos los elementos de la $@matriz y reemplace el comienzo de cada uno de ellos /path/to/dest/.

No conozco una forma de obtener lsresultados directamente como una lista de expansión de llaves. Si trató de masajear la salida de la **/expansión en una expansión de llave, necesitaría tener cuidado de:

  • escapar de las comas en la salida
  • escapar de cualquiera {o ${secuencia
  • asegúrese de que la cadena resultante no exceda el espacio de argumento de línea de comandos disponible

No lo recomendaría

Jeff Schaller
fuente
2

La pregunta es un duplicado entre sitios de /superuser/1389580/copy-directory-structure-only-at-year-end

Este tipo de tarea es un caso de uso clásico para mtree:

$ mkdir new-tree
$ mtree -cp old-tree | mtree -tdUp new-tree
.:      modification time (Tue Sep 24 14:27:07 2019, Tue Sep 24 16:34:57 2019, modified)
./bar missing (created)
./bar/bar2 missing (created)
./bar/bar2/bar3 missing (created)
./bar/bar2/bar3/bar4 missing (created)
./foo missing (created)
./foo/foo2 missing (created)
./foo/foo2/foo3 missing (created)

Lo anterior crea todos los directorios new-treeque estaban presentes en old-tree. mtreeSin embargo, no establece marcas de tiempo en los directorios recién creados, por lo que el árbol resultante se ve así:

$ find old-tree new-tree -ls
 20147  1 drwx--x---   4 jim   jim   5 Sep 24 14:27 old-tree
 20048  1 drwx--x---   3 jim   jim   4 Sep 24 14:27 old-tree/foo
 20363  1 -rw-------   1 jim   jim   0 Sep 24 14:27 old-tree/foo/file
 20073  1 drwx--x---   3 jim   jim   4 Sep 24 14:27 old-tree/foo/foo2
 20074  1 drwx--x---   2 jim   jim   3 Sep 24 14:27 old-tree/foo/foo2/foo3
 20365  1 -rw-------   1 jim   jim   0 Sep 24 14:27 old-tree/foo/foo2/foo3/file
 20364  1 -rw-------   1 jim   jim   0 Sep 24 14:27 old-tree/foo/foo2/file
 20051  1 drwx--x---   3 jim   jim   4 Sep 24 14:27 old-tree/bar
 20077  1 drwx--x---   3 jim   jim   4 Sep 24 14:27 old-tree/bar/bar2
 20368  1 -rw-------   1 jim   jim   0 Sep 24 14:27 old-tree/bar/bar2/file
 20078  1 drwx--x---   3 jim   jim   4 Sep 24 14:27 old-tree/bar/bar2/bar3
 20369  1 -rw-------   1 jim   jim   0 Sep 24 14:27 old-tree/bar/bar2/bar3/file
 20079  1 drwx--x---   2 jim   jim   3 Sep 24 14:27 old-tree/bar/bar2/bar3/bar4
 20370  1 -rw-------   1 jim   jim   0 Sep 24 14:27 old-tree/bar/bar2/bar3/bar4/file
 20366  1 -rw-------   1 jim   jim   0 Sep 24 14:27 old-tree/bar/file
 20362  1 -rw-------   1 jim   jim   0 Sep 24 14:27 old-tree/file
134489  1 drwx--x---   4 jim   jim   4 Sep 24 16:34 new-tree
134490  1 drwx--x---   3 jim   jim   3 Sep 24 16:34 new-tree/bar
134491  1 drwx--x---   3 jim   jim   3 Sep 24 16:34 new-tree/bar/bar2
134492  1 drwx--x---   3 jim   jim   3 Sep 24 16:34 new-tree/bar/bar2/bar3
134493  1 drwx--x---   2 jim   jim   2 Sep 24 16:34 new-tree/bar/bar2/bar3/bar4
134494  1 drwx--x---   3 jim   jim   3 Sep 24 16:34 new-tree/foo
134495  1 drwx--x---   3 jim   jim   3 Sep 24 16:34 new-tree/foo/foo2
134496  1 drwx--x---   2 jim   jim   2 Sep 24 16:34 new-tree/foo/foo2/foo3

Si prefiere que las new-treemarcas de tiempo coincidan old-tree, simplemente mtreevuelva a ejecutar . Como los directorios ya existen, mtreemodificará las marcas de tiempo para que coincidan con la especificación de origen:

$ mtree -cp old-tree | mtree -tdUp new-tree
.:      modification time (Tue Sep 24 14:27:07 2019, Tue Sep 24 16:34:57 2019, modified)
bar:    modification time (Tue Sep 24 14:27:07 2019, Tue Sep 24 16:34:57 2019, modified)
bar/bar2: 
        modification time (Tue Sep 24 14:27:07 2019, Tue Sep 24 16:34:57 2019, modified)
bar/bar2/bar3: 
        modification time (Tue Sep 24 14:27:07 2019, Tue Sep 24 16:34:57 2019, modified)
bar/bar2/bar3/bar4: 
        modification time (Tue Sep 24 14:27:07 2019, Tue Sep 24 16:34:57 2019, modified)
foo:    modification time (Tue Sep 24 14:27:07 2019, Tue Sep 24 16:34:57 2019, modified)
foo/foo2: 
        modification time (Tue Sep 24 14:27:07 2019, Tue Sep 24 16:34:57 2019, modified)
foo/foo2/foo3: 
        modification time (Tue Sep 24 14:27:07 2019, Tue Sep 24 16:34:57 2019, modified)
$ find old-tree new-tree -ls
 20147  1 drwx--x---   4 jim   jim   5 Sep 24 14:27 old-tree
 20048  1 drwx--x---   3 jim   jim   4 Sep 24 14:27 old-tree/foo
 20363  1 -rw-------   1 jim   jim   0 Sep 24 14:27 old-tree/foo/file
 20073  1 drwx--x---   3 jim   jim   4 Sep 24 14:27 old-tree/foo/foo2
 20074  1 drwx--x---   2 jim   jim   3 Sep 24 14:27 old-tree/foo/foo2/foo3
 20365  1 -rw-------   1 jim   jim   0 Sep 24 14:27 old-tree/foo/foo2/foo3/file
 20364  1 -rw-------   1 jim   jim   0 Sep 24 14:27 old-tree/foo/foo2/file
 20051  1 drwx--x---   3 jim   jim   4 Sep 24 14:27 old-tree/bar
 20077  1 drwx--x---   3 jim   jim   4 Sep 24 14:27 old-tree/bar/bar2
 20368  1 -rw-------   1 jim   jim   0 Sep 24 14:27 old-tree/bar/bar2/file
 20078  1 drwx--x---   3 jim   jim   4 Sep 24 14:27 old-tree/bar/bar2/bar3
 20369  1 -rw-------   1 jim   jim   0 Sep 24 14:27 old-tree/bar/bar2/bar3/file
 20079  1 drwx--x---   2 jim   jim   3 Sep 24 14:27 old-tree/bar/bar2/bar3/bar4
 20370  1 -rw-------   1 jim   jim   0 Sep 24 14:27 old-tree/bar/bar2/bar3/bar4/file
 20366  1 -rw-------   1 jim   jim   0 Sep 24 14:27 old-tree/bar/file
 20362  1 -rw-------   1 jim   jim   0 Sep 24 14:27 old-tree/file
134489  1 drwx--x---   4 jim   jim   4 Sep 24 14:27 new-tree
134490  1 drwx--x---   3 jim   jim   3 Sep 24 14:27 new-tree/bar
134491  1 drwx--x---   3 jim   jim   3 Sep 24 14:27 new-tree/bar/bar2
134492  1 drwx--x---   3 jim   jim   3 Sep 24 14:27 new-tree/bar/bar2/bar3
134493  1 drwx--x---   2 jim   jim   2 Sep 24 14:27 new-tree/bar/bar2/bar3/bar4
134494  1 drwx--x---   3 jim   jim   3 Sep 24 14:27 new-tree/foo
134495  1 drwx--x---   3 jim   jim   3 Sep 24 14:27 new-tree/foo/foo2
134496  1 drwx--x---   2 jim   jim   2 Sep 24 14:27 new-tree/foo/foo2/foo3
Jim L.
fuente