¿Copiar solo carpetas, no archivos?

16

¿Hay alguna manera de copiar un directorio completo, pero solo las carpetas? Tengo un archivo corrupto en algún lugar de mi directorio que causa que mis discos duros fallen.

Entonces, en lugar de copiar el archivo dañado en otro disco duro, solo quería copiar las carpetas, porque tengo scripts que buscan cientos de carpetas, y no quiero tener que crearlas manualmente.

Hice una búsqueda en el manual de cp, pero no pude ver nada (puede que me lo haya perdido)

Digamos que tengo esta estructura en mi HDD fallido:

dir1
    files
    dir2
        files
        files
        dir4
dir3
files

Todo lo que quiero es la estructura del directorio, no ningún archivo.

Así que terminaría con el nuevo HDD:

dir1
    dir2
        dir4
dir3

¡Esperando que alguien sepa algunos trucos!

Shannon
fuente
¿Quiere decir que solo quiere copiar el directorio estructurado o simplemente quiere excluir los archivos en el directorio de trabajo actual (y todos los demás archivos en subdirectorios más profundos son juegos)?
Oli
He agregado un ejemplo. lo siento por ser confuso
Shannon
1
Para su uso, rsynccopie la estructura del directorio Y conserve los permisos y atributos] ( stackoverflow.com/a/9242883/52074 ). El uso de plain mkdir -p no conserva los permisos y atributos .
Trevor Boyd Smith

Respuestas:

15

Si desea reflejar un esqueleto de directorio y no copiar archivos:

find -type d -links 2 -exec mkdir -p "/path/to/backup/{}" \;

Que está pasando aqui:

  • Buscar solo está seleccionando directorios
  • Estamos utilizando -links 2para encontrar los directorios más profundos posibles .
  • mkdir -p hará que falten directorios en el camino.

Lo he hecho así en lugar de hacerlo find -type d -exec mkdir -p "/path/to/backup/{}" \;porque reducirá una gran cantidad de mkdirllamadas. Podemos probar esto rápidamente con una pequeña prueba. Aquí está el árbol de prueba seguido de lo que ejecuté para comparar los dos comandos:

$ tree
.
├── dir1
│   ├── dir2
│   │   └── dir3
│   ├── dir7
│   └── dir8
└── dir9
    └── dir0

$ pr -m -t <(find -type d) <(find -type d -links 2)
.                               ./dir1/dir8
./dir1                          ./dir1/dir2/dir3
./dir1/dir8                     ./dir1/dir7
./dir1/dir2                     ./dir9/dir0
./dir1/dir2/dir3
./dir1/dir7
./dir9                  
./dir9/dir0 

Y eso solo mejorará en una solución de palabras reales con miles de directorios.

Oli
fuente
Este soy yo siendo un novato, sin embargo, ¿cómo estás buscando el antiguo directorio para copiar en la copia de seguridad? Aquí solo puedo ver un camino
Shannon el
Si no especifica una ruta, findutiliza el directorio de trabajo actual como punto de partida. Si desea utilizar otra ruta, use la sintaxis:find /path/to/search/ -type.....
Oli
¿Así que configuré mi directorio en una carpeta determinada que contiene el esqueleto que quiero copiar, ejecutar find -type d -exec mkdir -p "/media/jinglez/TVSeries/TV Series"/{}" \;y todo debería estar bien? Parece estar tomando un tiempo: /
Shannon
Ejecuto esto desde la terminal normal ¿verdad?
Shannon
1
Ambos son específicos para encontrar la cláusula ejecutiva. {} significa el nombre de archivo "encontrado" actual y \; es solo el escape para terminar la cláusula. Por lo que parece, hay un "extra en su código que no sirve para nada, estoy seguro ... Debería leer:find -type d -links 2 -exec mkdir -p "/media/jinglez/TVSeries/TV Series/{}" \;
Oli
2

Fácilmente hecho con python one-liner:

bash-4.3$ tree
.
├── ABC
├── set_pathname_icon.py
├── subdir1
│   ├── file1.abc
│   └── file2.abc
├── subdir2
│   ├── file1.abc
│   └── file2.abc
└── subdir3
    └── subdir4
        └── file1.txt

4 directories, 7 files
bash-4.3$ python -c 'import os,sys;dirs=[ r for r,s,f in os.walk(".") if r != "."];[os.makedirs(os.path.join(sys.argv[1],i)) for i in dirs]' ~/new_destination
bash-4.3$ tree ~/new_destination
/home/xieerqi/new_destination
├── subdir1
├── subdir2
└── subdir3
    └── subdir4

Como script, esto podría reescribirse así:

#!/usr/bin/env python
import os,sys
dirs=[ r for r,s,f in os.walk(".") if r != "."]
for i in dirs:
    os.makedirs(os.path.join(sys.argv[1],i)) 
Sergiy Kolodyazhnyy
fuente