2009-05-14 4 views
5

Donc, il semble y avoir quelques questions à propos de la suppression de fichiers/répertoires correspondant à certains cas, mais je cherche exactement le contraire: Supprimer TOUT dans un dossier qui NE FAIT PAS correspond à mes exemples fournis.Supprimer tous les fichiers/répertoires à l'exception de deux répertoires spécifiques

Par exemple, voici un arborescence exemple:

. 
|-- coke 
| |-- diet 
| |-- regular 
| `-- vanilla 
|-- icecream 
| |-- chocolate 
| |-- cookiedough 
| |-- cupcake 
| | |-- file1.txt 
| | |-- file2.txt 
| | |-- file3.txt 
| | |-- file4.txt 
| | `-- file5.txt 
| `-- vanilla 
|-- lol.txt 
|-- mtndew 
| |-- classic 
| |-- codered 
| |-- livewire 
| | |-- file1.txt 
| | |-- file2.txt 
| | |-- file3.txt 
| | |-- file4.txt 
| | `-- file5.txt 
| `-- throwback 
`-- pepsi 
    |-- blue 
    |-- classic 
    |-- diet 
    `-- throwback 

Je veux supprimer tout sauf les fichiers test/icecream/petit gâteau/et test/mtndew/Livewire /. Tout le reste peut aller, y compris la structure du répertoire. Alors, comment puis-je y parvenir? Langues Cela ne me dérangerait pas d'être dans: bash ou python.

Répondre

3

find « s -prune vient à l'esprit, mais il est une douleur pour le faire fonctionner pour des chemins spécifiques (icecream/cupcake/) plutôt que des répertoires spécifiques (cupcake/).

Personnellement, je venais d'utiliser cpio et dur lien (pour éviter d'avoir à les copier) les fichiers dans les répertoires que vous souhaitez conserver à un nouvel arbre puis retirez l'ancien:

find test -path 'test/icecream/cupcake/*' -o -path 'test/mtndew/livewire/*' | cpio -padluv test-keep 
rm -rf test 

Cela conservera également votre structure de répertoire existante pour les répertoires que vous avez l'intention de conserver.

0

utilisez find.

Votre commande ressemblera à quelque chose comme:

find $directory \(-prune 'some pattern' \) -delete 
+0

essayé, et il dit le texte suivant: find/home/Phuzion/test/\\ (-prune 'icecream/petit gâteau /' \\) -delete trouver: les chemins doivent précéder l'expression – phuzion

+0

De la page man pour find: "Parce que -delete implique -depth, vous ne pouvez pas utilement utiliser -prune et -delete ensemble." –

+0

La syntaxe correcte serait plus proche de "find $ répertoire -path ./pepsi/diet -prune -o -exec some-command '{}' \;" de toute façon pour éliminer ce message d'erreur. –

2

Vous pouvez faire quelque chose basé sur Python's os.walk function.

import os 
for root, dirs, files in os.walk(top, topdown=False): 
    for name in files: 
     os.remove(os.path.join(root, name)) 
    for name in dirs: 
     os.rmdir(os.path.join(root, name)) 

... il suffit d'ajouter quelque chose à ignorer les chemins qui vous intéressent

3

Tout "sauf" est la raison pour laquelle nous avons des if-statements; et pourquoi la liste des répertoires de os.walk est une liste mutable.

for path, dirs, files in os.walk('root'): 
    if 'coke' in dirs: 
     dirs.remove('coke') 
     dirs.remove('pepsi') 
2

Déplacez les éléments que vous souhaitez conserver ailleurs, puis supprimez ce qui reste.

0

A oneliner pour résoudre le problème:

trouver. | grep -v "test/icecream/cupcake /" | grep « test/mtndew/Livewire/» | xargs rm -r

supprimé car il ne fonctionne pas

cela pourrait vous causer des problèmes si des noms de fichiers avec un espace en eux, et il pourrait garder plus de fichiers alors vous voulez s'il y a d'autres arbres qui correspondent aux modèles.

Une solution un peu mieux:

find . |sed "s/.*/rm '&'/"|grep -v "rm './test/icecream/cupcake/"| grep -v "rm './test/mtndew/livewire/"|sh 

Pas vraiment testé, si elle se casse vous obtenez de garder les deux parties.

Edit: Comme Dennis souligne non seulement ses deux parties qu'il casse dans :-) corrigé les fautes de frappe dans le second exemple et enlevé la première

+0

Dans votre premier exemple, il y aura rm -r test/icecream qui inclura cupcake (par exemple). Donc, même si vous avez grillé les cupcakes, ils sont toujours "mangés". Le deuxième exemple contient quelques fautes de frappe et des guillemets simples déséquilibrés.Il devrait y avoir un espace après sed et le zéro devrait être une esperluette. –

+0

Vous avez toujours des guillemets simples déséquilibrés autour des chemins. Par exemple, il devrait être "rm" ./test/icecream/cupcake/ '" –

5

Cette commande quittera uniquement les fichiers désirés dans leurs répertoires d'origine:

find test \(! -path "test/mtndew/livewire/*" ! -path "test/icecream/cupcake/*" \) -delete 

Pas besoin de cpio. Il fonctionne sur Ubuntu, Debian 5 et Mac OS X.

Sous Linux, il indiquera qu'il ne peut pas supprimer les répertoires non vides, ce qui correspond exactement au résultat souhaité. Sur Mac OS X, il fera tranquillement la bonne chose.

+0

Ceci trouve un test et le supprime, supprimant ainsi les répertoires que vous essayez d'enregistrer. –

+0

Cela trouve un test et ne le supprime pas, car il est non vide. Existe-t-il des versions modernes de Linux ou d'Unix dans lesquelles cette commande échoue? –

+0

Désolé, j'ai fait une erreur en installant le test sur mon système. Votre exemple fonctionne correctement pour moi. –

0

Cela fonctionne pour moi avec trouver en utilisant deux étapes: d'abord supprimer les fichiers autorisés, puis leurs répertoires vides!

find -x -E ~/Desktop/test -not \(-type d -regex '.*/(cupcake|livewire)/*.*' -prune \) -print0 | xargs -0 ls -1 -dG 

# delete the files first 

# Mac OS X 10.4 
find -x -E ~/Desktop/test -not \(-type d -regex '.*/(cupcake|livewire)/*.*' -prune \) -type f -exec /bin/rm -fv '{}' \; 

# Mac OS X 10.5 
find -x -E ~/Desktop/test -not \(-type d -regex '.*/(cupcake|livewire)/*.*' -prune \) -type f -exec /bin/rm -fv '{}' + 

# delete empty directories 
find -x ~/Desktop/test -type d -empty -delete 
+0

Sur Ubuntu, find n'a pas -x -E, donc l'équivalent serait: find ~/Desktop/test -xdev -regextype posix-étendu-not \ (-type d -regex '. */(Cupcake | livewire) /*.* '-prune \) -print0 | xargs -0 ls -1 -dG –

+0

De même, il peut être nécessaire dans certains cas de protéger les répertoires vides que vous souhaitez conserver en utilisant la même expression regex dans la commande find -empty qui se trouve à la dernière étape de votre réponse. Vous pourriez préciser que votre première commande est un test de preuve de concept et ne fait pas partie des deux étapes que vous démontrez. –

0

Comme d'autres, je l'ai utilisé os.walk et os.path.join pour construire la liste des fichiers à supprimer, avec fnmatch.fnmatch pour sélectionner les fichiers qui doivent être inclus ou exclus:

#-------------------------------# 
# make list of files to display # 
#-------------------------------# 
displayList = [] 
for imageDir in args : 
    for root,dirs,files in os.walk(imageDir) : 
     for filename in files : 
      pathname = os.path.join(root, filename) 
      if fnmatch.fnmatch(pathname, options.includePattern) : 
       displayList.append(pathname) 


#----# now filter out excluded patterns #----# 
try : 
    if len(options.excludePattern) > 0 : 
     for pattern in options.excludePattern : 
      displayList = [pathname for pathname in displayList if not fnmatch.fnmatch(pathname, pattern) ] 
except (AttributeError, TypeError) : 
    pass 

Si fnmatch ne vous suffit pas, vous pouvez utiliser le module re pour tester des modèles.

Ici, j'ai construit la liste de fichiers avant de faire quoi que ce soit, mais vous pouvez traiter les fichiers au fur et à mesure qu'ils sont générés. Le bloc try/except ... est là au cas où mon instance de classe d'options n'a pas de modèle d'exclusion, ou si elle provoque une exception dans fnmatch parce que c'est un mauvais type.

Une limitation de cette méthode est que le premier comprend des fichiers correspondant à un motif, exclut alors. Si vous avez besoin de plus de flexibilité que cela (inclure le motif correspondant a, mais pas le motif b à moins que le motif c ...), alors le fragment ci-dessus n'est pas à la hauteur. En fait, à travers cet exercice, vous commencez à voir pourquoi la syntaxe de la commande find est telle qu'elle est. Semble maladroit, mais en fait c'est exactement le moyen de le faire. Mais si vous générez une liste, vous pouvez la filtrer en fonction des règles d'inclusion/exclusion dont vous avez besoin.

Une bonne chose à propos de la génération d'une liste est que vous pouvez le vérifier avant d'aller de l'avant avec la suppression. C'est en quelque sorte une option '--dryrun'. Vous pouvez le faire de manière interactive dans l'interpréteur python, imprimer la liste pour voir à quoi il ressemble, appliquer le filtre suivant, voir s'il a trop enlevé ou trop peu et ainsi de suite.

2
find /path/to/test/ -depth -mindepth 1 \ 
! -path "/path/to/test/icecream/cupcake/*" \ 
! -path "/path/to/test/icecream/cupcake" \ 
! -path "/path/to/test/icecream" \ 
! -path "/path/to/test/mtndew/livewire/*" \ 
! -path "/path/to/test/mtndew/livewire" \ 
! -path "/path/to/test/mtndew" 
-delete -print 

C'est un peu fastidieux d'écrire tous les chemins à préserver mais c'est la seule façon d'utiliser la recherche seule.

Questions connexes