J'essaye d'écrire un simple script Python 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.Comment obtenir tous les sous-répertoires immédiats en Python
Répondre
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))]
os.walk
est votre ami dans cette situation.
Droit de la documentation:
promenade() génère les noms de fichiers dans une arborescence de répertoires, en marchant l'arbre soit de haut en bas ou de bas en haut. Pour chaque répertoire de l'arborescence racine du répertoire top (y compris le sommet lui-même), il donne un triplet (dirpath, dirnames, noms de fichiers).
Sachez simplement que si vous voulez seulement les sous-répertoires de premier niveau s'échappent alors de l'itération os.walk après le premier ensemble de valeurs de retour. – yoyo
En utilisant le module CheminFichier Twisted:
from twisted.python.filepath import FilePath
def subdirs(pathObj):
for subpath in pathObj.walk():
if subpath.isdir():
yield subpath
if __name__ == '__main__':
for subdir in subdirs(FilePath(".")):
print "Subdirectory:", subdir
Étant donné que certains commentateurs ont demandé à ce que les avantages de l'utilisation des bibliothèques de Twisted pour cela est, je vais aller un peu au-delà de la question originale ici.
Il y a some improved documentation dans une branche qui explique les avantages de CheminFichier; vous pourriez vouloir lire cela.
Plus spécifiquement dans cet exemple: contrairement à la version de bibliothèque standard, cette fonction peut être implémentée avec sans les importations. La fonction "subdirs" est totalement générique, en ce sens qu'elle ne fonctionne que sur son argument. Afin de copier et déplacer les fichiers en utilisant la bibliothèque standard, vous devez dépendre du "open
" intégré, "listdir
", peut-être "isdir
" ou "os.walk
" ou "shutil.copy
". Peut-être "os.path.join
" aussi. Sans oublier le fait que vous avez besoin d'une chaîne passée un argument pour identifier le fichier réel. Jetons un coup d'oeil à la pleine application qui copie « de index.tpl » à « index.html » de chaque répertoire:
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 peuvent travailler sur tout FilePath
objet -comme. Ce qui signifie, entre autres, ZipPath
objets. 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 utiliser des noms importés et des dépendances implicites et effectuer généralement de la magie noire pour que vos tests fonctionnent. Avec CheminFichier, 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(...))
Comme j'ai peu d'expérience avec Twisted, j'accueille toujours des informations et des exemples supplémentaires; cette réponse est agréable à voir pour cela. Cela dit, étant donné que cette approche semble exiger beaucoup plus de travail que l'utilisation des modules python intégrés, et une installation Twisted, y a-t-il des avantages à utiliser ceci que vous pourriez ajouter à la réponse? –
La réponse de Glyph a probablement été inspirée par le fait que TwistedLore utilise également des fichiers .tpl. – Constantin
Eh bien, clairement je ne m'attends pas à l'inquisition espagnole :-) J'ai supposé que "* .tpl" était une référence générique à une extension abstraite signifiant "modèle", et non à un modèle Twisted spécifique (j'ai vu .tpl utilisé dans beaucoup de langues après tout). Bon à savoir. –
est ici une façon:
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: ne fonctionnera pas, car shutil.copy copiera dans le répertoire actuel, de sorte que vous finirez par écraser 'index.html' dans le répertoire actuel une fois pour chaque 'index.tpl' que vous trouverez dans l'arborescence du sous-répertoire . – nosklo
Correction du code, merci! –
Je viens d'écrire un code pour déplacer des machines virtuelles vmware autour, et a fini par utiliser pour réaliser la copie de fichiers os.path
et shutil
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.
import os, os.path
Pour (chemin complet) sous-répertoires immédiats 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 les derniers (les plus récents) sous-répertoire:
def LatestDirectory (d):
return max(SubDirPath(d), key=os.path.getmtime)
Pourquoi personne n'a mentionné glob
? glob
vous permet d'utiliser l'extension de chemin Unix-style, et est mon aller à la fonction pour presque tout ce qui doit trouver plus d'un nom de chemin. Il est très facile:
from glob import glob
paths = glob('*/')
Notez que glob
retournera le répertoire avec la barre oblique finale (comme unix se) alors que la plupart des solutions basées path
omettra la barre oblique finale.
Bonne solution, simple et fonctionne. Pour ceux qui ne veulent pas ce slash final, il peut utiliser 'paths = [p.replace ('/', '') pour p in glob ('* /')]'. –
Il peut être plus sûr de simplement couper le dernier caractère avec '[p [: - 1] pour p dans les chemins]', car cette méthode remplacera également toutes les barres obliques échappées du nom de fichier (pas communes). – ari
Encore plus sûr, utilisez la bande ('/') pour supprimer les barres obliques.De cette façon, vous ne coupez pas les caractères qui ne sont pas des barres obliques –
Cochez la case "Getting a list of all subdirectories in the current directory".
est ici une version Python 3:
import os
dir_list = next(os.walk('.'))[1]
print(dir_list)
Il serait plus clear si 'file_list' a été remplacé par' dir_list', car '[1]' retourne la liste des répertoires. – wisbucky
@wisbucky point juste, j'ai mis à jour ma réponse. –
** Extrêmement intelligent. ** Alors que l'efficacité n'a pas d'importance (_... elle fait totalement_), je suis curieux de savoir si ceci ou l'expression du générateur glob-based '(s.rstrip ("/") pour s dans glob (parent_dir + "* /")) 'est plus rapide. Mon soupçon intuitif est qu'une solution 'os.walk()' basée sur 'stat()' * devrait * être * profondément plus rapide que la globalisation de type shell. Malheureusement, il me manque la volonté de «timeit» et de le découvrir. –
Cette méthode fait bien tout en une seule fois.
from glob import glob
subd = [s.rstrip("/") for s in glob(parent_dir+"*/")]
Vous pouvez constater que la réponse acceptée à cette question précédente SO résout le problème: http://stackoverflow.com/questions/120656/directory-listing-in-python –