2017-03-10 1 views
3

Je veux construire un programme qui utilise du code de base pour lire un dossier et me dire combien de fichiers sont dans le dossier. Voici comment je le fais actuellement:python os.walk à un certain niveau

import os 

folders = ['Y:\\path1', 'Y:\\path2', 'Y:\\path3'] 
for stuff in folders: 
    for root, dirs, files in os.walk(stuff, topdown=True): 
     print("there are", len(files), "files in", root) 

Cela fonctionne très bien jusqu'à ce qu'il ya plusieurs dossiers dans le dossier « principal » car il peut retourner une longue liste junky des fichiers en raison du mauvais dossier/gestion de fichiers. Je voudrais donc aller au deuxième niveau tout au plus. exemple:

Main Folder 
---file_i_want 
---file_i_want 
---Sub_Folder 
------file_i_want <--* 
------file_i want <--* 
------Sub_Folder_2 
---------file_i_dont_want 
---------file_i_dont_want 

Je sais comment aller seul le premier niveau avec un break et del dirs[:] pris de this post et also this post.

import os 
import pandas as pd 

folders = ['Y:\\path1', 'Y:\\path2', 'Y:\\path3'] 
for stuff in folders: 
    for root, dirs, files in os.walk(stuff, topdown=True): 
     print("there are", len(files), "files in", root) 
     del dirs[:] # or a break here. does the same thing. 

Mais peu importe ma recherche je ne peux pas savoir comment aller deux couches de profondeur. Je ne suis peut-être pas en train de comprendre les autres articles sur le sujet ou quelque chose? Je pensais quelque chose comme del dirs[:2] mais en vain. Quelqu'un peut-il me guider ou m'expliquer comment accomplir cela?

+0

'dirs' correspond à tous les répertoires du répertoire courant, ce n'est pas la profondeur de l'arborescence des dossiers. –

+0

@PeterWood, ah! ça a du sens. Alors maintenant, je comprends pourquoi 'del dirs [: 2]' est idiot ... – MattR

+0

On dirait que vous utilisez Python 3. Est-ce correct? –

Répondre

5

vous pourriez faire comme ceci:

for root,dirs,files in os.walk(stuff): 
    if root[len(stuff)+1:].count(os.sep)<2: 
     for f in files: 
      print(os.path.join(root,f)) 

clé est: if root[len(stuff)+1:].count(os.sep)<2

Il supprime stuff + séparateur de root, donc résultat est par rapport à stuff. Comptez simplement le nombre de séparateurs de fichiers, et n'entrez pas la condition sauf si vous avez 0 ou 1 séparateurs.

Bien sûr, il analyse toujours la structure complète du fichier, mais à moins que ce ne soit très profond, cela fonctionnera.

Une autre solution serait d'utiliser seulement os.listdir récursivement (avec vérification de répertoire) avec un niveau de récursivité maximum, mais c'est un peu plus compliqué si vous n'en avez pas besoin. Comme il est pas difficile, voici une implémentation:

def scanrec(root): 
    rval = [] 

    def do_scan(start_dir,output,depth=0): 
     for f in os.listdir(start_dir): 
      ff = os.path.join(start_dir,f) 
      if os.path.isdir(ff): 
       if depth<2: 
        do_scan(ff,output,depth+1) 
      else: 
       output.append(ff) 

    do_scan(root,rval,0) 
    return rval 

print(scanrec(stuff)) # prints the list of files not below 2 deep 

Note: os.listdir et os.path.isfile effectuer 2 appels stat donc pas optimale. En Python 3.5, l'utilisation de os.scandir pourrait éviter ce double appel.

+0

C'est ce que je voulais. et j'apprécie vraiment la déclaration "Key is". Si vous pouviez bien m'expliquer ou me diriger vers une documentation sur la façon dont vous êtes arrivé à cette réponse? Je suis bloqué sur pourquoi les parenthèses dans 'root [len (stuff ...]' et quoi '.count (os.sep)' fait.Merci beaucoup – MattR

+0

Pourquoi pas 'break' quand' root [len (substance) + 1:]. Count (os.sep)> = 2'? En descendant, quand cela est vrai, il sera vrai pour toutes les autres valeurs de 'root' –

+0

@DavidCullen bon point. En fait, cela ne fonctionne pas, il semble ne s'appliquer qu'aux répertoires –

1

Vous pouvez compter les séparateurs et si elle est deux niveaux supprimer en profondeur le contenu de dirs si walk ne RECURSE pas plus profond:

import os 

MAX_DEPTH = 2 
folders = ['Y:\\path1', 'Y:\\path2', 'Y:\\path3'] 
for stuff in folders: 
    for root, dirs, files in os.walk(stuff, topdown=True): 
     print("there are", len(files), "files in", root) 
     if root.count(os.sep) - stuff.count(os.sep) == MAX_DEPTH - 1: 
      del dirs[:] 

Python documentation états suivants sur le comportement:

Lorsque topdown est True, l'appelant peut modifier la liste des noms de répertoire sur place (en utilisant peut-être une affectation del ou slice), et walk() ne se recurdera que dans les sous-répertoires dont les noms restent dans les noms de répertoire; ceci peut être utilisé pour élaguer la recherche, imposer un ordre spécifique de visite, ou même pour informer walk() sur les répertoires que l'appelant crée ou renomme avant de recommencer à marcher().

Notez que vous devez prendre en compte les séparateurs présents dans le folders. Par exemple, lorsque y:\path1 est marchée, la racine est y:\path mais vous ne voulez pas arrêter la récursion là.

+0

Merci de me pointer vers la documentation! est-il correct que 'root.count (os.sep)' compte la '' \\ '' dans la racine? – MattR

+1

@MattR: Oui, il compte \ (ou quel que soit le séparateur spécifique de l'os) dans la racine d'où nous devons soustraire les séparateurs présents dans le dossier initial. – niemmi