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.
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))]
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.
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)
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)
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).
Cette méthode fait tout en une fois.
from glob import glob
subd = [s.rstrip("/") for s in glob(parent_dir+"*/")]
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(...))
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.
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')
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')
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
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']