2011-10-20 9 views
7

Esiste un modo per filtrare una directory utilizzando il percorso assoluto?Filtra directory quando si utilizza shutil.copytree?

shutil.copytree(directory, 
       target_dir, 
       ignore = shutil.ignore_patterns("/Full/Path/To/aDir/Common")) 

Questo non sembra funzionare quando si cerca di filtrare la directory "Comune" si trova sotto "aDir". Se faccio questo:

shutil.copytree(directory, 
       target_dir, 
       ignore = shutil.ignore_patterns("Common")) 

Funziona, ma ogni directory chiamata comune sarà filtrato in questo "albero", che non è quello che voglio.

Qualche suggerimento?

Grazie.

risposta

10

È possibile effettuare la propria funzione di ignorare:

shutil.copytree('/Full/Path', 'target', 
       ignore=lambda directory, contents: ['Common'] if directory == '/Full/Path/To/aDir' else []) 

Oppure, se si vuole essere in grado di chiamare copytree con un percorso relativo:

import os.path 
def ignorePath(path): 
    def ignoref(directory, contents): 
    return (f for f in contents if os.abspath(os.path.join(directory, f)) == path) 
    return ignoref 

shutil.copytree('Path', 'target', ignore=ignorePath('/Full/Path/To/aDir/Common')) 

Dalla documentazione:

Se viene specificato ignora, deve essere un callable che riceverà come argomenti la directory che è vi sito da copytree() e un elenco dei suoi contenuti , come restituito da os.listdir(). Poiché copytree() è chiamato in modo ricorsivo, l'ignora callable verrà chiamato una volta per ogni directory copiata. Il callable deve restituire una sequenza di nomi di directory e file relativi alla directory corrente (ad esempio un sottoinsieme degli elementi nel suo secondo argomento); questi nomi saranno quindi ignorati nel processo di copia. ignore_patterns() può essere usato per creare tale callable che ignora i nomi in base a modelli glob-style.

+0

Piccola correzione, la funzione ignoref deve restituire l'elenco (ad esempio [f per f in ...] anziché generatore. –

3

L'API per shutil.ignore_patterns() non supporta percorsi assoluti, ma è banalmente facile eseguire il rollover della propria variante.

Come punto di partenza, guardare il codice sorgente per * ignore_patterns *:

def ignore_patterns(*patterns): 
    """Function that can be used as copytree() ignore parameter. 

    Patterns is a sequence of glob-style patterns 
    that are used to exclude files""" 
    def _ignore_patterns(path, names): 
     ignored_names = [] 
     for pattern in patterns: 
      ignored_names.extend(fnmatch.filter(names, pattern)) 
     return set(ignored_names) 
    return _ignore_patterns 

Si può vedere che restituisce una funzione che accetta un percorso e un elenco di nomi, e restituisce una serie di nomi ignorare. Per supportare il tuo caso d'uso, crea la tua funzione simile che utilizza l'argomento percorso. Passa la tua funzione al parametro ignore nella chiamata a copytree().

In alternativa, non utilizzare shutil così com'è. Il codice sorgente è breve e dolce, quindi non è difficile da tagliare, incollare e personalizzare.

3

Si desidera impostare la propria funzione di ignoranza, che controlla la directory corrente in elaborazione e restituisce un elenco contenente "Comune" solo se la directory è "/ Completo/Percorso/A/aDir".

def ignore_full_path_common(dir, files): 
    if dir == '/Full/Path/To/aDir': 
     return ['Common'] 
    return [] 

shutil.copytree(directory, target_dir, ignore=ignore_full_path_common) 
Problemi correlati