web-dev-qa-db-fra.com

Comment obtenir tous les sous-répertoires immédiats en Python

J'essaie d'écrire un script Python simple qui va copier un index.tpl dans index.html dans tous les sous-répertoires (à quelques exceptions près). 

Je m'embourbe en essayant d'obtenir la liste des sous-répertoires.

106
Steven Noble
import os
def get_immediate_subdirectories(a_dir):
    return [name for name in os.listdir(a_dir)
            if os.path.isdir(os.path.join(a_dir, name))]
189
RichieHindle

Pourquoi personne n'a mentionné glob ? glob vous permet d'utiliser une extension de chemin d'accès de style Unix. Je peux y accéder pour presque tout ce qui doit trouver plus d'un nom de chemin. Cela rend très facile:

from glob import glob
paths = glob('*/')

Notez que glob renverra le répertoire avec la barre oblique finale (comme le ferait Unix) alors que la plupart des solutions basées sur path omettront la barre oblique finale.

62
ari

Cochez " Obtenir une liste de tous les sous-répertoires du répertoire courant ".

Voici une version de Python 3:

import os

dir_list = next(os.walk('.'))[1]

print(dir_list)
19
Geng Jiawen
import os, os.path

Pour obtenir des sous-répertoires immédiats (chemin complet) dans un répertoire:

def SubDirPath (d):
    return filter(os.path.isdir, [os.path.join(d,f) for f in os.listdir(d)])

Pour obtenir le dernier sous-répertoire (le plus récent):

def LatestDirectory (d):
    return max(SubDirPath(d), key=os.path.getmtime)
18
Milan

os.walk est votre ami dans cette situation.

Directement de la documentation:

walk () génère les noms de fichier dans une arborescence de répertoires, en la parcourant de haut en bas ou de bas en haut. Pour chaque répertoire de l’arborescence dont la racine est située en haut du répertoire (y compris le sommet lui-même), cela donne un 3-Tuple (dirpath, noms de fichiers, noms de fichiers). 

11
Andrew Cox

Cette méthode fait tout en une fois.

from glob import glob
subd = [s.rstrip("/") for s in glob(parent_dir+"*/")]
8
SuaveSouris

Utilisation du module FilePath de Twisted:

from twisted.python.filepath import FilePath

def subdirs(pathObj):
    for subpath in pathObj.walk():
        if subpath.isdir():
            yield subpath

if __== '__main__':
    for subdir in subdirs(FilePath(".")):
        print "Subdirectory:", subdir

Certains commentateurs ayant demandé quels sont les avantages d'utiliser les bibliothèques de Twisted pour cela, je vais aller un peu au-delà de la question initiale.


Il y a une documentation améliorée dans une branche qui explique les avantages de FilePath; vous voudrez peut-être lire cela.

Plus spécifiquement dans cet exemple: contrairement à la version standard de la bibliothèque, cette fonction peut être implémentée avec no imports. La fonction "subdirs" est totalement générique, en ce sens qu'elle n'agit que sur son argument. Pour copier et déplacer les fichiers à l’aide de la bibliothèque standard, vous devez vous fier à la structure "open", "listdir", éventuellement "isdir" ou "os.walk" ou "shutil.copy". Peut-être aussi "os.path.join". Sans oublier le fait que vous avez besoin d'une chaîne de caractères et d'un argument pour identifier le fichier réel. Jetons un coup d'œil à l'implémentation complète qui copiera le "index.tpl" de chaque répertoire dans "index.html":

def copyTemplates(topdir):
    for subdir in subdirs(topdir):
        tpl = subdir.child("index.tpl")
        if tpl.exists():
            tpl.copyTo(subdir.child("index.html"))

La fonction "subdirs" ci-dessus peut fonctionner sur tout objet de type FilePath-. Ce qui signifie, entre autres, des objets ZipPath. Malheureusement, ZipPath est en lecture seule pour le moment, mais il pourrait être étendu pour prendre en charge l'écriture.

Vous pouvez également transmettre vos propres objets à des fins de test. Afin de tester les API utilisant os.path suggérées ici, vous devez identifier les noms importés et les dépendances implicites et effectuer généralement une magie noire pour que vos tests fonctionnent. Avec FilePath, vous faites quelque chose comme ceci:

class MyFakePath:
    def child(self, name):
        "Return an appropriate child object"

    def walk(self):
        "Return an iterable of MyFakePath objects"

    def exists(self):
        "Return true or false, as appropriate to the test"

    def isdir(self):
        "Return true or false, as appropriate to the test"
...
subdirs(MyFakePath(...))
7
Glyph

Je viens d'écrire du code pour déplacer des machines virtuelles vmware, et j'ai finalement utilisé os.path et shutil pour effectuer la copie de fichiers entre sous-répertoires.

def copy_client_files (file_src, file_dst):
    for file in os.listdir(file_src):
            print "Copying file: %s" % file
            shutil.copy(os.path.join(file_src, file), os.path.join(file_dst, file))

Ce n'est pas très élégant, mais ça marche.

3
Rob Carr

Voici un moyen:

import os
import shutil

def copy_over(path, from_name, to_name):
  for path, dirname, fnames in os.walk(path):
    for fname in fnames:
      if fname == from_name:
        shutil.copy(os.path.join(path, from_name), os.path.join(path, to_name))


copy_over('.', 'index.tpl', 'index.html')
1
Scott Kirkwood
import pathlib


def list_dir(dir):
    path = pathlib.Path(dir)
    dir = []
    try:
        for item in path.iterdir():
            if item.is_dir():
                dir.append(item)
        return dir
    except FileNotFoundError:
        print('Invalid directory')
0
Yossarian42
def get_folders_in_directories_recursively(self, directory, index=0):
    folder_list = list()
    parent_directory = directory

    for path, subdirs, _ in os.walk(directory):
        if not index:
            for sdirs in subdirs:
                folder_path = "{}/{}".format(path, sdirs)
                folder_list.append(folder_path)
        Elif path[len(parent_directory):].count('/') + 1 == index:
            for sdirs in subdirs:
                folder_path = "{}/{}".format(path, sdirs)
                folder_list.append(folder_path)

    return folder_list

La fonction suivante peut être appelée en tant que:

get_folders_in_directories_recursively (répertoire, index = 1) -> donne la liste des dossiers du premier niveau

get_folders_in_directories_recursively (répertoire) -> donne tous les sous-dossiers

0
Kanish Mathew
import glob
import os

def child_dirs(path):
     cd = os.getcwd()        # save the current working directory
     os.chdir(path)          # change directory 
     dirs = glob.glob("*/")  # get all the subdirectories
     os.chdir(cd)            # change directory to the script original location
     return dirs

La fonction child_dirs prend un chemin dans un répertoire et renvoie la liste des sous-répertoires immediate qu'il contient.

dir
 |
  -- dir_1
  -- dir_2

child_dirs('dir') -> ['dir_1', 'dir_2']
0
Amjad