Come ottenere tutte le sottodirectory immediate in Python
Domanda
Sto cercando di scrivere un semplice script Python che copi un index.tpl in index.html in tutte le sottodirectory (con alcune eccezioni).
Mi sto impantanando cercando di ottenere l'elenco delle sottodirectory.
Soluzione
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))]
Altri suggerimenti
Perché nessuno ha menzionato glob
? glob
ti consente di utilizzare l'espansione del percorso in stile Unix, ed è il mio go per funzionare per quasi tutto ciò che ha bisogno di trovare più di un nome di percorso. Lo rende molto semplice:
from glob import glob
paths = glob('*/')
Nota che glob
restituirà la directory con la barra finale (come farebbe unix) mentre la maggior parte delle soluzioni basate su percorso
ometterà la barra finale.
Controlla " Ottenere un elenco di tutte le sottodirectory nella directory corrente " ;.
Ecco una versione di Python 3:
import os
dir_list = next(os.walk('.'))[1]
print(dir_list)
import os, os.path
Per ottenere sottodirectory immediate (percorso completo) in una directory:
def SubDirPath (d):
return filter(os.path.isdir, [os.path.join(d,f) for f in os.listdir(d)])
Per ottenere la sottodirectory più recente (più recente):
def LatestDirectory (d):
return max(SubDirPath(d), key=os.path.getmtime)
os.walk
è tuo amico in questa situazione.
Direttamente dalla documentazione:
walk () genera i nomi dei file in un albero di directory, camminando l'albero in alto o in basso. Per ogni directory nell'albero radicata nella directory top (incluso top stessa), produce una 3 tupla (dirpath, dirnames, nomi di file).
Questo metodo fa bene tutto in una volta.
from glob import glob
subd = [s.rstrip("/") for s in glob(parent_dir+"*/")]
Utilizzando il modulo FilePath di 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
Poiché alcuni commentatori hanno chiesto quali siano i vantaggi dell'utilizzo delle librerie di Twisted per questo, andrò un po 'oltre la domanda originale qui.
C'è della documentazione migliorata in un ramo che spiega i vantaggi di FilePath; potresti volerlo leggere.
Più precisamente in questo esempio: a differenza della versione standard della libreria, questa funzione può essere implementata con nessuna importazione . "Subdir" " la funzione è totalmente generica, in quanto non opera altro che il suo argomento. Per copiare e spostare i file utilizzando la libreria standard, devi dipendere da " open
" builtin, " listdir
" ;, forse " isdir
" o " os.walk
" o " shutil.copy
" ;. Forse " os.path.join
" pure. Per non parlare del fatto che è necessario che una stringa abbia passato un argomento per identificare il file effettivo. Diamo un'occhiata all'implementazione completa che copierà ogni directory " index.tpl " a " index.html " ;:
def copyTemplates(topdir):
for subdir in subdirs(topdir):
tpl = subdir.child("index.tpl")
if tpl.exists():
tpl.copyTo(subdir.child("index.html"))
Il " subdir " la funzione sopra può funzionare su qualsiasi oggetto FilePath
. Il che significa, tra l'altro, oggetti ZipPath
. Purtroppo ZipPath
è di sola lettura in questo momento, ma potrebbe essere esteso per supportare la scrittura.
Puoi anche passare i tuoi oggetti a scopo di test. Per testare le API che utilizzano os.path suggerite qui, devi cercare i nomi importati e le dipendenze implicite ed eseguire generalmente la magia nera per far funzionare i test. Con FilePath, fai qualcosa del genere:
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(...))
Ho appena scritto del codice per spostare le macchine virtuali VMware e ho finito con os.path
e shutil
per realizzare la copia dei file tra le sottodirectory.
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))
Non è terribilmente elegante, ma funziona.
Ecco un modo:
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')
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 seguente funzione può essere chiamata come:
get_folders_in_directories_recursively (directory, index = 1) - > fornisce l'elenco delle cartelle di primo livello
get_folders_in_directories_recursively (directory) - > fornisce tutte le sottocartelle
Devo menzionare la libreria path.py , che utilizzo molto spesso.
Il recupero delle sottodirectory immediate diventa così semplice:
my_dir.dirs ()
L'esempio di lavoro completo è:
from path import Path
my_directory = Path("path/to/my/directory")
subdirs = my_directory.dirs()
NB: my_directory può ancora essere manipolata come una stringa, poiché Path è una sottoclasse di string, ma fornisce una serie di metodi utili per manipolare i percorsi
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 funzione child_dirs
prende un percorso in una directory e restituisce un elenco delle sottodirectory immediate in essa.
dir
|
-- dir_1
-- dir_2
child_dirs('dir') -> ['dir_1', 'dir_2']
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')