OVH Cloud OVH Cloud

glob recursif

14 réponses
Avatar
R12y
Bonjour,

Je recherche un moyen de lister tous les fichiers .ogg contenus sous un
PATH donné.
Juste à titre d'exemple, en ZSH, c'est faisable avec "**/*.ogg"
Ce "**/*.ogg" me trouve tous les .ogg sous le PATH courant, sans limite de
profondeur.

Avec glob.glob(), on peut faire, mais le souci c'est que je ne
trouve pas coment on peut faire pour ne pas limiter la profondeur de
recherche. Manifestement on doit mettre autant de "*/" qu'on veut que la
recherche soit profonde.

Une piste?

Voici ce que moi j'obtients (prompt ipython):

In [30]: import glob
In [31]: glob.glob("*/*.ogg")
Out[31]:
['Desktop/tanandrazana.ogg',
'Desktop/tanandrazana-e.ogg',
'Desktop/rozaline.ogg',
'Desktop/dadah_fort_dauphin_kilimity.ogg',
'download/tanin-vid.ogg',
'download/pubmaquette.ogg',
'download/pub.ogg']

In [32]: glob.glob("*/*/*.ogg")
Out[32]:
['music/instruesyram/ao_amponay_zao.ogg',
'music/instruesyram/ao_amponay.ogg',
'music/instruesyram/ao_tsaiko_foana.ogg',
'music/instruesyram/aza_kivy.ogg',
'music/instruesyram/jesosy_avia.ogg',
'music/instruesyram/oh_hitako.ogg',
'music/instruesyram/ry_raiko_oh.ogg',
'music/instruesyram/ry_tanora.ogg',
'music/instruesyram/tafaray.ogg',
'music/instruesyram/taona_maro.ogg',
'music/instruesyram/zazavavy.ogg']

In [33]:

--
My Debian/apt repo:
My Fedora/yum Repo:
http://www.locataire-serveur.info/sections/liens/fedora-core-yum

10 réponses

1 2
Avatar
R12y
R12y :
Une piste?


à priori, mon auto-brainstorm me dit que je devrai faire avec un os.walk()

w=os.walk("/home/mihamina/")
for (path,dirs,files) in w:
for f in files:
if re.compile(r'[.]*.ogg$').search(f):
print path+'/'+f

Ou alors, si on veut stocker dans une liste:

w=os.walk("/home/mihamina/")
l=[]
for (path,dirs,files) in w:
for f in files:
if re.compile(r'[.]*.ogg$').search(f):
l.append(path+'/'+f)

Si il y a mieux, dites-moi surtout hein :-)

--
My Debian/apt repo:
My Fedora/yum Repo:
http://www.locataire-serveur.info/sections/liens/fedora-core-yum

Avatar
R12y
if re.compile(r'[.]*.ogg$').search(f):


re.compile('.+.ogg$').match(f)

semble plus approprié.

--
My Debian/apt repo:
My Fedora/yum Repo:
http://www.locataire-serveur.info/sections/liens/fedora-core-yum

Avatar
Amaury Forgeot d'Arc
et en plus, c'est totalement inefficace de recompiler la même regexp à
chaque itération...


Pas tant que ça : les 100 dernières regexp compilées sont gardées dans
un dictionnaire (cf. le code dans sre.py:_compile())

--
Amaury

Avatar
Méta-MCI
Bonsoir !

Juste un détail : la portabilité de glob est... limitée

@-salutations

Michel Claveau
Avatar
Bruno Desthuilliers
R12y :

Une piste?



à priori, mon auto-brainstorm me dit que je devrai faire avec un os.walk()

w=os.walk("/home/mihamina/")
for (path,dirs,files) in w:
for f in files:
if re.compile(r'[.]*.ogg$').search(f):


Tu t'emmerdes bien la vie pour rien:
if f.endswith('.ogg')


Avatar
Bruno Desthuilliers

R12y :

Une piste?




à priori, mon auto-brainstorm me dit que je devrai faire avec un
os.walk()

w=os.walk("/home/mihamina/")
for (path,dirs,files) in w:
for f in files:
if re.compile(r'[.]*.ogg$').search(f):



Tu t'emmerdes bien la vie pour rien:
if f.endswith('.ogg')


(tapé enter avant d'avoir fini, désolé)

et en plus, c'est totalement inefficace de recompiler la même regexp à
chaque itération...

from os import walk
from os.path import join as path_join
import re

# parcours filtré générique
def filterwalk(basepath, filter_cb, **kw):
filteredfiles = []
for path, dirs, files in walk(basepath):
for filename in files:
if filter_cb(basepath, filename, **kw):
filteredfiles.append((basepath, filename))
for dirname in dirs:
filteredfiles += filterwalk(path_join(basepath, dirname),
filter_cb,
**kw)
return filteredfiles

# parcours filtré par une regexp
def regexp_filter_files(basepath, regexp):
exp = re.compile(regexp)
filter_cb = lambda basepath, filename:
exp.match(path_join(basepath, filename))
return [path_join(*parts)
for parts in filterwalk(basepath, filter_cb)]

NB1: pas testé, et je n'ai jamais utilisé os.walk, donc il y a des
chances que ça merdoie

NB2: si tu veux quelque chose de plus proche des wildcards, il y a
fnmatch (sur lequel s'appuie glob BTW)



Avatar
R12y
Bruno Desthuilliers :

et en plus, c'est totalement inefficace de recompiler la même regexp à
chaque itération...


Effectivement, le fait de le faire à chaque fois peut-ête évité.
Je conçois que même si comme Armaury le dit c'et "mis en cache", prendre
la sale habitude d'itérer à la barbarre c'est mal.

from os import walk
from os.path import join as path_join
import re

# parcours filtré générique
def filterwalk(basepath, filter_cb, **kw):


Et... filter_cb c'est quoi?
J'ai pas encore testé le code, je tente de comprendre, et pas vu ça fait
quoi.

Merci.

--
My Debian/apt repo:
My Fedora/yum Repo:
http://www.locataire-serveur.info/sections/liens/fedora-core-yum

Avatar
bruno at modulix
Amaury Forgeot d'Arc wrote:

et en plus, c'est totalement inefficace de recompiler la même regexp à
chaque itération...


Pas tant que ça : les 100 dernières regexp compilées sont gardées dans
un dictionnaire (cf. le code dans sre.py:_compile())


Un bon point pour les concepteurs de ce module.

Ceci étant, je ne me baserais pas sur l'espoir que quelqu'un a pensé à
maintenir un cache quelque part pour me décharger de toute
responsabilité concernant la conception mes algos... Extraire d'une
boucle tout calcul ne dépendant pas de la boucle, c'est franchement du
niveau grand débutant.

En outre, le fait qu'il y a un cache ne change rien au coût des appels
de fonctions inutiles.

Mes deux centimes...

--
bruno desthuilliers
python -c "print '@'.join(['.'.join([w[::-1] for w in p.split('.')]) for
p in ''.split('@')])"


Avatar
bruno at modulix
R12y wrote:
Bruno Desthuilliers :


et en plus, c'est totalement inefficace de recompiler la même regexp à
chaque itération...



Effectivement, le fait de le faire à chaque fois peut-ête évité.
Je conçois que même si comme Armaury le dit c'et "mis en cache", prendre
la sale habitude d'itérer à la barbarre c'est mal.


from os import walk
from os.path import join as path_join
import re

# parcours filtré générique
def filterwalk(basepath, filter_cb, **kw):



Et... filter_cb c'est quoi?


cb -> callback

C'est une fonction de rappel qui sera utilisée pour déterminer quels
fichiers doivent être retournés.

J'ai pas encore testé le code, je tente de comprendre, et pas vu ça fait
quoi.


Ca parcourt récursivement une arborescence de fichier et renvoie la
liste (chemin, nom_fichier) des fichiers ayant satisfait le prédicat
exprimé par la fonction de rappel.

Découpler le mécanisme général (parcours récursif et récupération des
éléments à conserver) du cas particulier (critère de sélection des
éléments à récupérer) permet d'éviter de recoder inutilement le même
algo pour chaque cas particulier.


--
bruno desthuilliers
python -c "print '@'.join(['.'.join([w[::-1] for w in p.split('.')]) for
p in ''.split('@')])"


Avatar
R12y
bruno at modulix :

cb -> callback
C'est une fonction de rappel qui sera utilisée pour déterminer quels
fichiers doivent être retournés.


Merci.

J'ai jetté un oeil à "Python en concentré" à la BU ce matin et j'ai
compris le système du call back, parceque os.path.walk() le prévoit.

J'ai fait un bilan de mes recherches ici:
http://locataire-serveur.info/sections/python/python-et-listing J'y décris
ce que j'ai pu faire avec glob.glob(), os.walk() et os.path.walk(). Sans
prétentions. Si y en a qui veulent faire des remarques en douceur, je suis
preneur.

--
My Debian/apt repo:
My Fedora/yum Repo:
http://www.locataire-serveur.info/sections/liens/fedora-core-yum

1 2