Scorrere le directory con Python


158

Devo scorrere le sottodirectory di una determinata directory e cercare i file. Se ricevo un file devo aprirlo e cambiare il contenuto e sostituirlo con le mie linee.

Ho provato questo:

import os

rootdir ='C:/Users/sid/Desktop/test'

for subdir, dirs, files in os.walk(rootdir):
    for file in files:
        f=open(file,'r')
        lines=f.readlines()
        f.close()
        f=open(file,'w')
        for line in lines:
            newline = "No you are not"
            f.write(newline)
        f.close()

ma sto ricevendo un errore. Che cosa sto facendo di sbagliato?


12
"Un errore" - qualche errore in particolare?
Daniel Roseman,

1
Per favore, potresti spiegare qualcosa su ciò che speri di fare con i file / le directory una volta che riesci a farli funzionare come previsto? Fornisci anche i dettagli dell'errore.
ChrisProsser,

1
Il messaggio di errore che sto ottenendo è che il file cool.txt non è stato trovato. Nella mia cartella di test ho un'altra cartella chiamata src e nella cartella src ho un'altra cartella chiamata main, in questa cartella ho cool.txt
Wolf

4
puoi semplicemente scrivere l'errore nella domanda? è oltre noioso e inutile dover leggere i commenti per trovarlo.
Charlie Parker,

1
oltre un anno dopo non riesco a credere di essere tornato a richiedere la pubblicazione dell'errore? @Wolf
Charlie Parker,

Risposte:


301

La vera passeggiata attraverso le directory funziona come l'hai codificata. Se sostituisci il contenuto del ciclo interno con una semplice printistruzione, puoi vedere che ogni file è stato trovato:

import os
rootdir = 'C:/Users/sid/Desktop/test'

for subdir, dirs, files in os.walk(rootdir):
    for file in files:
        print os.path.join(subdir, file)

Se si verificano ancora errori durante l'esecuzione di quanto sopra, si prega di fornire il messaggio di errore.


Aggiornato per Python3

import os
rootdir = 'C:/Users/sid/Desktop/test'

for subdir, dirs, files in os.walk(rootdir):
    for file in files:
        print(os.path.join(subdir, file))

1
C: / Users / sid / Desktop / test \ src \ app / cool.txt C: / Users / sid / Desktop / test \ src \ app / woohoo.txt Ya nella dichiarazione aperta del mio codice, penso di dover dare il percorso assoluto al file. import os rootdir = 'C: / Users / spemmara / Desktop / test / src / app /' per subdir, dirs, file in os.walk (rootdir): per file in file: f = open (subdir + '/' + file , 'r') lines = f.readlines () f.close () f = open (subdir + '/' + file, 'w') per line in lines: newline = "hey i know" f.write (newline) f.close () Grazie amico. Risolto
Lupo,

3
Ciao! Tieni presente che la "stampa" in Python 3 richiede parentesi, altrimenti restituisce un errore di sintassi. Spero che questo ti aiuti!
Tommaso Di Noto,

14

Un altro modo per restituire tutti i file nelle sottodirectory è utilizzare il pathlibmodulo , introdotto in Python 3.4, che fornisce un approccio orientato agli oggetti per la gestione dei percorsi del filesystem (Pathlib è disponibile anche su Python 2.7 tramite il modulo pathlib2 su PyPi ):

from pathlib import Path

rootdir = Path('C:/Users/sid/Desktop/test')
# Return a list of regular files only, not directories
file_list = [f for f in rootdir.glob('**/*') if f.is_file()]

# For absolute paths instead of relative the current dir
file_list = [f for f in rootdir.resolve().glob('**/*') if f.is_file()]

A partire da Python 3.5, il globmodulo supporta anche la ricerca di file ricorsivi:

import os
from glob import iglob

rootdir_glob = 'C:/Users/sid/Desktop/test/**/*' # Note the added asterisks
# This will return absolute paths
file_list = [f for f in iglob('**/*', recursive=True) if os.path.isfile(f)]

L' file_listuno o l'altro degli approcci precedenti può essere ripetuto senza la necessità di un ciclo nidificato:

for f in file_list:
    print(f) # Replace with desired operations

1
Cosa è preferibile qui per Python 3.6?
PhoenixDev,

@PhoenixDev Non ho sentito parlare di un approccio raccomandato rispetto all'altro in generale. Preferisco usare pathlibme stesso, principalmente perché mi piace la sintassi dei metodi orientata agli oggetti. Esistono altre differenze, come la libreria dei percorsi che restituisce classi di percorso specifiche anziché le stringhe e le funzioni disponibili differiscono tra le librerie (ad es. os.path.expanduser('~')Vs Path.home()). Sfoglia la documentazione e vedi quale approccio preferisci.
joelostblom,

Invece di aggiungere **il modello glob, puoi usare rglob.
Georgy,

12

A partire dal 2020 , glob.iglob(path/**, recursive=True)sembra la soluzione più pitonica , ovvero:

import glob, os

for filename in glob.iglob('/pardadox-music/**', recursive=True):
    if os.path.isfile(filename): # filter dirs
        print(filename)

Produzione:

/pardadox-music/modules/her1.mod
/pardadox-music/modules/her2.mod
...

Note:
1 - glob.iglob

glob.iglob(pathname, recursive=False)

Restituisce un iteratore che restituisce gli stessi valori glob()senza memorizzarli tutti contemporaneamente.

2 - Se ricorsivo è True, il modello '**'corrisponderà a qualsiasi file e zero o più directoriese subdirectories.

3 - Se la directory contiene file che iniziano con,  .questi non verranno associati per impostazione predefinita. Ad esempio, considera una directory contenente  card.gif e .card.gif:

>>> import glob
>>> glob.glob('*.gif') ['card.gif'] 
>>> glob.glob('.c*')['.card.gif']

4 - Puoi anche usare rglob(pattern), che è lo stesso di chiamare  glob() con l' **/aggiunta di fronte al modello relativo dato.


1
Questa soluzione Pythonic non elenca i file nascosti (aka dotfile) mentre quello accettato lo fa.
ashrasmun,

@ashrasmun Quello che dici è ben spiegato in docs.python.org/3/library/glob.html
CONvid19
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.