Copier uniquement les dossiers et non les fichiers?

16

Existe-t-il un moyen de copier un répertoire entier, mais uniquement les dossiers? J'ai un fichier corrompu quelque part dans mon répertoire, ce qui provoque l'échec de mes disques durs.

Donc, au lieu de copier le fichier corrompu sur un autre disque dur, je voulais simplement copier les dossiers, car j'ai des scripts qui recherchent des centaines de dossiers, et je ne veux pas avoir à les créer manuellement tous.

J'ai cherché dans le manuel de cp, mais je n'ai rien vu (je l'ai peut-être manqué)

Disons que j'ai cette structure sur mon disque dur défaillant:

dir1
    files
    dir2
        files
        files
        dir4
dir3
files

Tout ce que je veux, c'est la structure du répertoire, pas de fichiers du tout.

Je me retrouverais donc avec le nouveau disque dur:

dir1
    dir2
        dir4
dir3

En espérant que quelqu'un connaisse quelques astuces!

Shannon
la source
Voulez-vous dire que vous voulez simplement copier la structure du répertoire ou voulez-vous simplement exclure les fichiers du répertoire de travail actuel (et tous les autres fichiers des sous-répertoires plus profonds sont du jeu)?
Oli
J'ai ajouté un exemple. désolé d'être déroutant
Shannon
1
Pour info, rsynccopiez la structure du répertoire ET conservez les autorisations et les attributs] ( stackoverflow.com/a/9242883/52074 ). L'utilisation de plain mkdir -p ne préserve pas les autorisations et les attributs .
Trevor Boyd Smith

Réponses:

15

Si vous souhaitez mettre en miroir un squelette de répertoire et ne copier aucun fichier:

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

Que se passe t-il ici:

  • Rechercher ne fait que sélectionner des répertoires
  • Nous utilisons -links 2pour trouver les répertoires les plus profonds possibles .
  • mkdir -p fera tous les répertoires manquants en cours de route.

Je l'ai fait comme ça plutôt que find -type d -exec mkdir -p "/path/to/backup/{}" \;parce que ça va couper tout un tas d' mkdirappels. Nous pouvons rapidement le prouver avec un petit test. Voici l'arbre de test suivi de ce que j'ai exécuté pour comparer les deux commandes:

$ 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 

Et cela ne fera que s'améliorer dans une solution réelle avec des milliers de répertoires.

Oli
la source
C'est moi étant un noob, mais comment cherchez-vous l'ancien répertoire à copier dans la sauvegarde? Je ne peux voir qu'un seul chemin ici
Shannon
Si vous ne spécifiez pas de chemin, findutilise le répertoire de travail actuel comme point de départ. Si vous souhaitez utiliser un autre chemin, utilisez la syntaxe:find /path/to/search/ -type.....
Oli
J'ai donc mis mon répertoire dans un certain dossier qui contient le squelette que je veux copier, exécuter find -type d -exec mkdir -p "/media/jinglez/TVSeries/TV Series"/{}" \;et tout devrait bien se passer ? Cela semble prendre du temps: /
Shannon
Je lance cela à partir du terminal normal, non?
Shannon
1
Ils sont tous deux spécifiques à la clause exec de find. {} signifie le nom de fichier "trouvé" actuel et \; est juste l'évasion pour mettre fin à la clause. À première vue, il y a un extra "dans votre code jusqu'à pas bon, je suis sûr ... Devrait lire:find -type d -links 2 -exec mkdir -p "/media/jinglez/TVSeries/TV Series/{}" \;
Oli
2

Assez facile à faire avec 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

En tant que script, cela pourrait être réécrit comme suit:

#!/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
la source