percorso - rinominare file python




Come elenco tutti i file di una directory? (20)

Come posso elencare tutti i file di una directory in Python e aggiungerli a una list ?


Ottieni un elenco di file con Python 2 e 3

Ho anche realizzato un breve video qui: Python: come ottenere un elenco di file in una directory

os.listdir ()

o ..... come ottenere tutti i file (e le directory) nella directory corrente (Python 3)

Il modo più semplice per avere il file nella directory corrente in Python 3 è questo. È davvero semplice; usa il modulo os e la funzione listdir () e avrai il file in quella directory (e le eventuali cartelle che si trovano nella directory, ma non avrai il file nella sottodirectory, per cui puoi usare walk - lo farò parlarne più tardi).

>>> import os
>>> arr = os.listdir()
>>> arr
['$RECYCLE.BIN', 'work.txt', '3ebooks.txt', 'documents']

Utilizzando glob

Ho trovato glob più facile selezionare file dello stesso tipo o con qualcosa in comune. Guarda il seguente esempio:

import glob

txtfiles = []
for file in glob.glob("*.txt"):
    txtfiles.append(file)

Utilizzando la comprensione delle liste

import glob

mylist = [f for f in glob.glob("*.txt")]

Ottenere il nome completo del percorso con os.path.abspath

Come hai notato, non hai il percorso completo del file nel codice sopra. Se è necessario avere il percorso assoluto, è possibile utilizzare un'altra funzione del modulo _getfullpathname chiamato _getfullpathname , inserendo il file che si ottiene da os.listdir() come argomento. Ci sono altri modi per avere il percorso completo, come vedremo in seguito (ho sostituito, come suggerito da mexmex, _getfullpathname con abspath ).

>>> import os
>>> files_path = [os.path.abspath(x) for x in os.listdir()]
>>> files_path
['F:\\documenti\applications.txt', 'F:\\documenti\collections.txt']

Ottieni il nome completo del percorso di un tipo di file in tutte le sottodirectory con walk

Lo trovo molto utile per trovare cose in molte directory e mi ha aiutato a trovare un file su cui non ricordavo il nome:

import os

# Getting the current work directory (cwd)
thisdir = os.getcwd()

# r=root, d=directories, f = files
for r, d, f in os.walk(thisdir):
    for file in f:
        if ".docx" in file:
            print(os.path.join(r, file))

os.listdir (): recupera i file nella directory corrente (Python 2)

In Python 2 tu, se vuoi la lista dei file nella directory corrente, devi dare l'argomento come '.' o os.getcwd () nel metodo os.listdir.

>>> import os
>>> arr = os.listdir('.')
>>> arr
['$RECYCLE.BIN', 'work.txt', '3ebooks.txt', 'documents']

Per salire nell'albero delle directory

>>> # Method 1
>>> x = os.listdir('..')

# Method 2
>>> x= os.listdir('/')

Ottieni file: os.listdir () in una particolare directory (Python 2 e 3)

>>> import os
>>> arr = os.listdir('F:\\python')
>>> arr
['$RECYCLE.BIN', 'work.txt', '3ebooks.txt', 'documents']

Ottieni i file di una particolare sottodirectory con os.listdir ()

import os

x = os.listdir("./content")

os.walk ('.') - directory corrente

>>> import os
>>> arr = next(os.walk('.'))[2]
>>> arr
['5bs_Turismo1.pdf', '5bs_Turismo1.pptx', 'esperienza.txt']

modulo glob: tutti i file

import glob
print(glob.glob("*"))

out:['content', 'start.py']

next (os.walk ('.')) e os.path.join ('dir', 'file')

>>> import os
>>> arr = []
>>> for d,r,f in next(os.walk("F:\_python")):
>>>     for file in f:
>>>         arr.append(os.path.join(r,file))
...
>>> for f in arr:
>>>     print(files)

>output

F:\\_python\\dict_class.py
F:\\_python\\programmi.txt

next (os.walk ('F: \') - ottieni il percorso completo - la comprensione degli elenchi

>>> [os.path.join(r,file) for r,d,f in next(os.walk("F:\\_python")) for file in f]
['F:\\_python\\dict_class.py', 'F:\\_python\\programmi.txt']

os.walk - get full path - tutti i file in sotto dir

x = [os.path.join(r,file) for r,d,f in os.walk("F:\\_python") for file in f]

>>>x
['F:\\_python\\dict.py', 'F:\\_python\\progr.txt', 'F:\\_python\\readl.py']

os.listdir () - ottiene solo i file txt

>>> arr_txt = [x for x in os.listdir() if x.endswith(".txt")]
>>> print(arr_txt)
['work.txt', '3ebooks.txt']

glob - ottieni solo file txt

>>> import glob
>>> x = glob.glob("*.txt")
>>> x
['ale.txt', 'alunni2015.txt', 'assenze.text.txt', 'text2.txt', 'untitled.txt']

Usare glob per ottenere il percorso completo dei file

Se dovrei avere bisogno del percorso assoluto dei file:

>>> from path import path
>>> from glob import glob
>>> x = [path(f).abspath() for f in glob("F:\*.txt")]
>>> for f in x:
...  print(f)
...
F:\acquistionline.txt
F:\acquisti_2018.txt
F:\bootstrap_jquery_ecc.txt

Altro uso di glob

Se voglio tutti i file nella directory:

>>> x = glob.glob("*")

Utilizzando os.path.isfile per evitare le directory nell'elenco

import os.path
listOfFiles = [f for f in os.listdir() if os.path.isfile(f)]
print(listOfFiles)

> output

['a simple game.py', 'data.txt', 'decorator.py']

Usare pathlib da (Python 3.4)

import pathlib

>>> flist = []
>>> for p in pathlib.Path('.').iterdir():
...  if p.is_file():
...   print(p)
...   flist.append(p)
...
error.PNG
exemaker.bat
guiprova.mp3
setup.py
speak_gui2.py
thumb.PNG

Se vuoi usare la comprensione delle liste

>>> flist = [p for p in pathlib.Path('.').iterdir() if p.is_file()]

* Puoi usare anche solo pathlib.Path () invece di pathlib.Path (".")

Usa il metodo glob in pathlib.Path ()

import pathlib

py = pathlib.Path().glob("*.py")
for file in py:
    print(file)

produzione:

stack_overflow_list.py
stack_overflow_list_tkinter.py

Ottieni tutti e solo i file con os.walk

import os
x = [i[2] for i in os.walk('.')]
y=[]
for t in x:
    for f in t:
        y.append(f)

>>> y
['append_to_list.py', 'data.txt', 'data1.txt', 'data2.txt', 'data_180617', 'os_walk.py', 'READ2.py', 'read_data.py', 'somma_defaltdic.py', 'substitute_words.py', 'sum_data.py', 'data.txt', 'data1.txt', 'data_180617']

Ottieni solo i file con successivo e cammina in una directory

>>> import os
>>> x = next(os.walk('F://python'))[2]
>>> x
['calculator.bat','calculator.py']

Ottieni solo directory con next e cammina in una directory

>>> import os
>>> next(os.walk('F://python'))[1] # for the current dir use ('.')
['python3','others']

Ottieni tutti i nomi delle sottodirectory con walk

>>> for r,d,f in os.walk("F:\_python"):
...  for dirs in d:
...   print(dirs)
...
.vscode
pyexcel
pyschool.py
subtitles
_metaprogramming
.ipynb_checkpoints

os.scandir () da Python 3.5 su

>>> import os
>>> x = [f.name for f in os.scandir() if f.is_file()]
>>> x
['calculator.bat','calculator.py']

# Another example with scandir (a little variation from docs.python.org)
# This one is more efficient than os.listdir.
# In this case, it shows the files only in the current directory
# where the script is executed.

>>> import os
>>> with os.scandir() as i:
...  for entry in i:
...   if entry.is_file():
...    print(entry.name)
...
ebookmaker.py
error.PNG
exemaker.bat
guiprova.mp3
setup.py
speakgui4.py
speak_gui2.py
speak_gui3.py
thumb.PNG
>>>

Ex. 1: Quanti file ci sono nelle sottodirectory?

In questo esempio, cerchiamo il numero di file che sono inclusi in tutta la directory e nelle sue sottodirectory.

import os

def count(dir, counter=0):
    "returns number of files in dir and subdirs"
    for pack in os.walk(dir):
        for f in pack[2]:
            counter += 1
    return dir + " : " + str(counter) + "files"

print(count("F:\\python"))

> output

>'F:\\\python' : 12057 files'

Es.2: Come copiare tutti i file da una directory a un'altra?

Uno script per fare ordine nel tuo computer trovando tutti i file di un tipo (predefinito: pptx) e copiandoli in una nuova cartella.

import os
import shutil
from path import path

destination = "F:\\file_copied"
# os.makedirs(destination)

def copyfile(dir, filetype='pptx', counter=0):
    "Searches for pptx (or other - pptx is the default) files and copies them"
    for pack in os.walk(dir):
        for f in pack[2]:
            if f.endswith(filetype):
                fullpath = pack[0] + "\\" + f
                print(fullpath)
                shutil.copy(fullpath, destination)
                counter += 1
    if counter > 0:
        print("------------------------")
        print("\t==> Found in: `" + dir + "` : " + str(counter) + " files\n")

for dir in os.listdir():
    "searches for folders that starts with `_`"
    if dir[0] == '_':
        # copyfile(dir, filetype='pdf')
        copyfile(dir, filetype='txt')


> Output

_compiti18\Compito Contabilità 1\conti.txt
_compiti18\Compito Contabilità 1\modula4.txt
_compiti18\Compito Contabilità 1\moduloa4.txt
------------------------
==> Found in: `_compiti18` : 3 files

Ex. 3: Come ottenere tutti i file in un file txt

Nel caso in cui desideri creare un file txt con tutti i nomi di file:

import os
mylist = ""
with open("filelist.txt", "w", encoding="utf-8") as file:
    for eachfile in os.listdir():
        mylist += eachfile + "\n"
    file.write(mylist)

Esempio: txt con tutti i file di un disco rigido

"""We are going to save a txt file with all the files in your directory.
We will use the function walk()

"""

import os

# see all the methods of os
# print(*dir(os), sep=", ")
listafile = []
percorso = []
with open("lista_file.txt", "w", encoding='utf-8') as testo:
    for root, dirs, files in os.walk("D:\\"):
        for file in files:
            listafile.append(file)
            percorso.append(root + "\\" + file)
            testo.write(file + "\n")
listafile.sort()
print("N. of files", len(listafile))
with open("lista_file_ordinata.txt", "w", encoding="utf-8") as testo_ordinato:
    for file in listafile:
        testo_ordinato.write(file + "\n")

with open("percorso.txt", "w", encoding="utf-8") as file_percorso:
    for file in percorso:
        file_percorso.write(file + "\n")

os.system("lista_file.txt")
os.system("lista_file_ordinata.txt")
os.system("percorso.txt")

Tutto il file di C: \\ in un file di testo

Questa è una versione più breve del codice precedente. Cambiare la cartella in cui iniziare a cercare i file se è necessario iniziare da un'altra posizione. Questo codice genera 50 mb su file di testo sul mio computer con qualcosa di meno di 500.000 righe con file con il percorso completo.

import os

with open("file.txt", "w", encoding="utf-8") as filewrite:
    for r, d, f in os.walk("C:\\"):
        for file in f:
            filewrite.write(f"{r + file}\n")    

Una funzione per cercare un certo tipo di file

importazione os

def searchfiles(extension='.ttf'):
    "Create a txt file with all the file of a type"
    with open("file.txt", "w", encoding="utf-8") as filewrite:
        for r, d, f in os.walk("C:\\"):
            for file in f:
                if file.endswith(extension):
                    filewrite.write(f"{r + file}\n")

# looking for ttf file (fonts)
searchfiles('ttf')

Parte prima 1

Note preliminari

  • Sebbene esista una chiara differenziazione tra i termini di file e directory nel testo della domanda, alcuni potrebbero obiettare che le directory sono in realtà file speciali
  • L'affermazione: " tutti i file di una directory " possono essere interpretati in due modi:
    1. Tutti i discendenti diretti (o di livello 1) solo
    2. Tutti i discendenti nell'intero albero delle directory (compresi quelli nelle sottodirectory)
  • Quando la domanda è stata posta, immagino che Python 2 , fosse la versione LTS , comunque gli esempi di codice saranno eseguiti da Python 3 ( .5 ) (li terrò come Python 2 il più possibile compatibile, inoltre, qualsiasi codice appartenente a Python che sto per postare, è dalla v3.5.4 - se non diversamente specificato). Ciò ha conseguenze legate a un'altra parola chiave nella domanda: " aggiungili in una lista ":

    • Nelle versioni pre Python 2.2 , le sequenze (iterabili) erano per lo più rappresentate da liste (tuple, insiemi, ...)
    • In Python 2.2 , è stato introdotto il concetto di generatore ( [Python]: Generatori ) - per gentile concessione di [Python]: la dichiarazione di rendimento ). Col passare del tempo, le controparti dei generatori hanno iniziato ad apparire per le funzioni che hanno restituito / lavorato con le liste
    • In Python 3 , il generatore è il comportamento predefinito
    • Ora, non so se restituire un elenco sia ancora obbligatorio (o un generatore farebbe altrettanto), ma passare un generatore al costruttore di list , ne creerà un elenco (e lo consumerà anche). L'esempio seguente illustra le differenze su [Python]: map ( function, iterable, ... )
    Python 2.7.10 (default, Mar  8 2016, 15:02:46) [MSC v.1600 64 bit (AMD64)] on win32
    Type "help", "copyright", "credits" or "license" for more information.
    >>> m = map(lambda x: x, [1, 2, 3])  # Just a dummy lambda function
    >>> m, type(m)
    ([1, 2, 3], <type 'list'>)
    >>> len(m)
    3
    


    Python 3.5.4 (v3.5.4:3f56838, Aug  8 2017, 02:17:05) [MSC v.1900 64 bit (AMD64)] on win32
    Type "help", "copyright", "credits" or "license" for more information.
    >>> m = map(lambda x: x, [1, 2, 3])
    >>> m, type(m)
    (<map object at 0x000001B4257342B0>, <class 'map'>)
    >>> len(m)
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    TypeError: object of type 'map' has no len()
    >>> lm0 = list(m)  # Construct a list out of the generator
    >>> lm0, type(lm0)
    ([1, 2, 3], <class 'list'>)
    >>>
    >>> lm1 = list(m)  # Construct a list out of the same generator
    >>> lm1, type(lm1)  # Empty list this time - generator already consumed
    ([], <class 'list'>)
    
  • Gli esempi saranno basati su una directory chiamata root_dir con la seguente struttura (questo esempio è per Win , ma ho duplicato anche l'albero delle cartelle per Ux ( Lnx )):

    E:\Work\Dev\\q003207219>tree /f "root_dir"
    Folder PATH listing for volume Work
    Volume serial number is 00000029 3655:6FED
    E:\WORK\DEV\\Q003207219\ROOT_DIR
    │   file0
    │   file1
    │
    ├───dir0
    │   ├───dir00
    │   │   │   file000
    │   │   │
    │   │   └───dir000
    │   │           file0000
    │   │
    │   ├───dir01
    │   │       file010
    │   │       file011
    │   │
    │   └───dir02
    │       └───dir020
    │           └───dir0200
    ├───dir1
    │       file10
    │       file11
    │       file12
    │
    ├───dir2
    │   │   file20
    │   │
    │   └───dir20
    │           file200
    │
    └───dir3
    


soluzioni

Approcci programmatici:

  1. [Python]: os. listdir ( percorso = '.' )

    Restituisce una lista contenente i nomi delle voci nella directory data dal percorso. L'elenco è in ordine arbitrario e non include le voci speciali '.' e '..' ...


    >>> import os
    >>> root_dir = "root_dir"  # Path relative to current dir (os.getcwd())
    >>>
    >>> os.listdir(root_dir)  # List all the items in root_dir
    ['dir0', 'dir1', 'dir2', 'dir3', 'file0', 'file1']
    >>>
    >>> [item for item in os.listdir(root_dir) if os.path.isfile(os.path.join(root_dir, item))]  # Filter the items and only keep files (strip out directories)
    ['file0', 'file1']
    

    Ecco un esempio più elaborato ( code_os_listdir.py ):

    import os
    from pprint import pformat
    
    
    def _get_dir_content(path, include_folders, recursive):
        entries = os.listdir(path)
        for entry in entries:
            entry_with_path = os.path.join(path, entry)
            if os.path.isdir(entry_with_path):
                if include_folders:
                    yield entry_with_path
                if recursive:
                    for sub_entry in _get_dir_content(entry_with_path, include_folders, recursive):
                        yield sub_entry
            else:
                yield entry_with_path
    
    
    def get_dir_content(path, include_folders=True, recursive=True, prepend_folder_name=True):
        path_len = len(path) + len(os.path.sep)
        for item in _get_dir_content(path, include_folders, recursive):
            yield item if prepend_folder_name else item[path_len:]
    
    
    def _get_dir_content_old(path, include_folders, recursive):
        entries = os.listdir(path)
        ret = list()
        for entry in entries:
            entry_with_path = os.path.join(path, entry)
            if os.path.isdir(entry_with_path):
                if include_folders:
                    ret.append(entry_with_path)
                if recursive:
                    ret.extend(_get_dir_content_old(entry_with_path, include_folders, recursive))
            else:
                ret.append(entry_with_path)
        return ret
    
    
    def get_dir_content_old(path, include_folders=True, recursive=True, prepend_folder_name=True):
        path_len = len(path) + len(os.path.sep)
        return [item if prepend_folder_name else item[path_len:] for item in _get_dir_content_old(path, include_folders, recursive)]
    
    
    def main():
        root_dir = "root_dir"
        ret0 = get_dir_content(root_dir, include_folders=True, recursive=True, prepend_folder_name=True)
        lret0 = list(ret0)
        print(ret0, len(lret0), pformat(lret0))
        ret1 = get_dir_content_old(root_dir, include_folders=False, recursive=True, prepend_folder_name=False)
        print(len(ret1), pformat(ret1))
    
    
    if __name__ == "__main__":
        main()
    

    Note :

    • Ci sono due implementazioni:
      • Uno che utilizza i generatori (ovviamente in questo esempio sembra inutile, dal momento che converto il risultato in una lista immediatamente)
      • Quello classico (i nomi delle funzioni terminano in _old )
    • La ricorsione è usata (per entrare nelle sottodirectory)
    • Per ogni implementazione ci sono due funzioni:
      • Uno che inizia con un carattere di sottolineatura ( _ ): "privato" (non dovrebbe essere chiamato direttamente) - questo fa tutto il lavoro
      • Quello pubblico (wrapper over precedente): rimuove solo il percorso iniziale (se richiesto) dalle voci restituite. È una brutta implementazione, ma è l'unica idea che potrei venire a questo punto
    • In termini di prestazioni, i generatori sono generalmente un po 'più veloci (considerando sia la creazione che i tempi di iterazione ), ma non li ho testati in funzioni ricorsive, e sto anche iterando all'interno della funzione sui generatori interni - non so come prestazioni amichevole è quello
    • Gioca con gli argomenti per ottenere risultati diversi


    Uscita :

    (py35x64_test) E:\Work\Dev\\q003207219>"e:\Work\Dev\VEnvs\py35x64_test\Scripts\python.exe" "code_os_listdir.py"
    <generator object get_dir_content at 0x000001BDDBB3DF10> 22 ['root_dir\\dir0',
     'root_dir\\dir0\\dir00',
     'root_dir\\dir0\\dir00\\dir000',
     'root_dir\\dir0\\dir00\\dir000\\file0000',
     'root_dir\\dir0\\dir00\\file000',
     'root_dir\\dir0\\dir01',
     'root_dir\\dir0\\dir01\\file010',
     'root_dir\\dir0\\dir01\\file011',
     'root_dir\\dir0\\dir02',
     'root_dir\\dir0\\dir02\\dir020',
     'root_dir\\dir0\\dir02\\dir020\\dir0200',
     'root_dir\\dir1',
     'root_dir\\dir1\\file10',
     'root_dir\\dir1\\file11',
     'root_dir\\dir1\\file12',
     'root_dir\\dir2',
     'root_dir\\dir2\\dir20',
     'root_dir\\dir2\\dir20\\file200',
     'root_dir\\dir2\\file20',
     'root_dir\\dir3',
     'root_dir\\file0',
     'root_dir\\file1']
    11 ['dir0\\dir00\\dir000\\file0000',
     'dir0\\dir00\\file000',
     'dir0\\dir01\\file010',
     'dir0\\dir01\\file011',
     'dir1\\file10',
     'dir1\\file11',
     'dir1\\file12',
     'dir2\\dir20\\file200',
     'dir2\\file20',
     'file0',
     'file1']
    


  1. [Python]: os. scandir ( path = '.' ) ( !!! Python 3.5 + !!! anche se penso che per le versioni precedenti fosse un modulo separato (anch'esso portato su Python 2 ))

    Restituisce un iteratore di os.DirEntry oggetti corrispondenti alle voci nella directory data dal percorso . Le voci sono fornite in ordine arbitrario e le voci speciali '.' e '..' non sono inclusi.

    L'uso di scandir () invece di listdir () può aumentare significativamente le prestazioni del codice che richiede anche il tipo di file o le informazioni sugli attributi del file, poiché os.DirEntry oggetti os.DirEntry espongono queste informazioni se il sistema operativo le fornisce durante la scansione di una directory. Tutti i metodi os.DirEntry possono eseguire una chiamata di sistema, ma is_dir() e is_file() solito richiedono solo una chiamata di sistema per i collegamenti simbolici; os.DirEntry.stat() richiede sempre una chiamata di sistema su Unix ma richiede solo uno per i collegamenti simbolici su Windows.


    >>> import os
    >>> root_dir = os.path.join(".", "root_dir")  # Explicitly prepending current directory
    >>> root_dir
    '.\\root_dir'
    >>>
    >>> scandir_iterator = os.scandir(root_dir)
    >>> scandir_iterator
    <nt.ScandirIterator object at 0x00000268CF4BC140>
    >>> [item.path for item in scandir_iterator]
    ['.\\root_dir\\dir0', '.\\root_dir\\dir1', '.\\root_dir\\dir2', '.\\root_dir\\dir3', '.\\root_dir\\file0', '.\\root_dir\\file1']
    >>>
    >>> [item.path for item in scandir_iterator]  # Will yield an empty list as it was consumed by previous iteration (automatically performed by the list comprehension)
    []
    >>>
    >>> scandir_iterator = os.scandir(root_dir)  # Reinitialize the generator
    >>> for item in scandir_iterator :
    ...     if os.path.isfile(item.path):
    ...             print(item.name)
    ...
    file0
    file1
    

    Note :

    • È simile a os.listdir
    • Ma è anche più flessibile (e offre più funzionalità), più Python ic (e in alcuni casi, più veloce)


  1. [Python]: os. walk ( top, topdown = True, onerror = None, followlinks = False )

    Genera i nomi dei file in un albero delle directory camminando sull'albero dall'alto verso il basso o dal basso verso l'alto. Per ogni directory nella radice di root nella directory superiore (incluso top stesso), produce una tupla di 3 ( dirpath , dirnames filenames , filenames ).


    >>> import os
    >>> root_dir = os.path.join(os.getcwd(), "root_dir")  # Specify the full path
    >>> root_dir
    'E:\\Work\\Dev\\\\q003207219\\root_dir'
    >>>
    >>> walk_generator = os.walk(root_dir)
    >>> root_dir_entry = next(walk_generator)  # First entry corresponds to the root dir (that was passed as an argument)
    >>> root_dir_entry
    ('E:\\Work\\Dev\\\\q003207219\\root_dir', ['dir0', 'dir1', 'dir2', 'dir3'], ['file0', 'file1'])
    >>>
    >>> root_dir_entry[1] + root_dir_entry[2]  # Display the dirs and the files (that are direct descendants) in a single list
    ['dir0', 'dir1', 'dir2', 'dir3', 'file0', 'file1']
    >>>
    >>> [os.path.join(root_dir_entry[0], item) for item in root_dir_entry[1] + root_dir_entry[2]]  # Display all the entries in the previous list by their full path
    ['E:\\Work\\Dev\\\\q003207219\\root_dir\\dir0', 'E:\\Work\\Dev\\\\q003207219\\root_dir\\dir1', 'E:\\Work\\Dev\\\\q003207219\\root_dir\\dir2', 'E:\\Work\\Dev\\\\q003207219\\root_dir\\dir3', 'E:\\Work\\Dev\\\\q003207219\\root_dir\\file0', 'E:\\Work\\Dev\\\\q003207219\\root_dir\\file1']
    >>>
    >>> for entry in walk_generator:  # Display the rest of the elements (corresponding to every subdir)
    ...     print(entry)
    ...
    ('E:\\Work\\Dev\\\\q003207219\\root_dir\\dir0', ['dir00', 'dir01', 'dir02'], [])
    ('E:\\Work\\Dev\\\\q003207219\\root_dir\\dir0\\dir00', ['dir000'], ['file000'])
    ('E:\\Work\\Dev\\\\q003207219\\root_dir\\dir0\\dir00\\dir000', [], ['file0000'])
    ('E:\\Work\\Dev\\\\q003207219\\root_dir\\dir0\\dir01', [], ['file010', 'file011'])
    ('E:\\Work\\Dev\\\\q003207219\\root_dir\\dir0\\dir02', ['dir020'], [])
    ('E:\\Work\\Dev\\\\q003207219\\root_dir\\dir0\\dir02\\dir020', ['dir0200'], [])
    ('E:\\Work\\Dev\\\\q003207219\\root_dir\\dir0\\dir02\\dir020\\dir0200', [], [])
    ('E:\\Work\\Dev\\\\q003207219\\root_dir\\dir1', [], ['file10', 'file11', 'file12'])
    ('E:\\Work\\Dev\\\\q003207219\\root_dir\\dir2', ['dir20'], ['file20'])
    ('E:\\Work\\Dev\\\\q003207219\\root_dir\\dir2\\dir20', [], ['file200'])
    ('E:\\Work\\Dev\\\\q003207219\\root_dir\\dir3', [], [])
    

    Note :

    • Sotto le scene, utilizza os.listdir( os.scandirdove disponibile)
    • Fa il sollevamento pesante ricorrendo in sottocartelle


  1. [Python]: glob. glob ( pathname, *, recursive = False ) ( [Python]: glob. iglob ( pathname, *, recursive = False ) )

    Restituisce una lista eventualmente vuota di nomi di percorsi che corrispondono a pathname , che deve essere una stringa contenente una specifica di percorso. il nome del percorso può essere assoluto (simile /usr/src/Python-1.5/Makefile) o relativo (come ../../Tools/*/*.gif) e può contenere caratteri jolly in stile shell. I link simbolici spezzati sono inclusi nei risultati (come nella shell).
    ...
    Modificato nella versione 3.5 : Supporto per glob ricorsivi con "**".


    >>> import glob, os
    >>> wildcard_pattern = "*"
    >>> root_dir = os.path.join("root_dir", wildcard_pattern)  # Match every file/dir name
    >>> root_dir
    'root_dir\\*'
    >>>
    >>> glob_list = glob.glob(root_dir)
    >>> glob_list
    ['root_dir\\dir0', 'root_dir\\dir1', 'root_dir\\dir2', 'root_dir\\dir3', 'root_dir\\file0', 'root_dir\\file1']
    >>>
    >>> [item.replace("root_dir" + os.path.sep, "") for item in glob_list]  # Strip the dir name and the path separator from begining
    ['dir0', 'dir1', 'dir2', 'dir3', 'file0', 'file1']
    >>>
    >>> for entry in glob.iglob(root_dir + "*", recursive=True):
    ...     print(entry)
    ...
    root_dir\
    root_dir\dir0
    root_dir\dir0\dir00
    root_dir\dir0\dir00\dir000
    root_dir\dir0\dir00\dir000\file0000
    root_dir\dir0\dir00\file000
    root_dir\dir0\dir01
    root_dir\dir0\dir01\file010
    root_dir\dir0\dir01\file011
    root_dir\dir0\dir02
    root_dir\dir0\dir02\dir020
    root_dir\dir0\dir02\dir020\dir0200
    root_dir\dir1
    root_dir\dir1\file10
    root_dir\dir1\file11
    root_dir\dir1\file12
    root_dir\dir2
    root_dir\dir2\dir20
    root_dir\dir2\dir20\file200
    root_dir\dir2\file20
    root_dir\dir3
    root_dir\file0
    root_dir\file1
    

    Note :

    • usi os.listdir
    • Per alberi di grandi dimensioni (soprattutto se recursiveè attivo), iglobè preferibile
    • Consente il filtraggio avanzato in base al nome (a causa del carattere jolly)


  1. [Python]: class pathlib. Path ( * pathsegments ) ( !!! Python 3 + !!! non so se backported)

    >>> import pathlib
    >>> root_dir = "root_dir"
    >>> root_dir_instance = pathlib.Path(root_dir)
    >>> root_dir_instance
    WindowsPath('root_dir')
    >>> root_dir_instance.name
    'root_dir'
    >>> root_dir_instance.is_dir()
    True
    >>>
    >>> [item.name for item in root_dir_instance.glob("*")]  # Wildcard searching for all direct descendants
    ['dir0', 'dir1', 'dir2', 'dir3', 'file0', 'file1']
    >>>
    >>> [os.path.join(item.parent.name, item.name) for item in root_dir_instance.glob("*") if not item.is_dir()]  # Display paths (including parent) for files only
    ['root_dir\\file0', 'root_dir\\file1']
    

    Note :

    • Questo è un modo per raggiungere il nostro obiettivo
    • È lo stile OOP dei percorsi di gestione
    • Offre molte funzionalità


  1. [Python]: dircache.listdir (path) ( !!! rimosso in Python 3 !!! )

    • Ma, secondo $ {PYTHON_SRC_DIR} /Lib/dircache.py : ~ # 20 + (dalla v2.7.14 ), è solo un (sottile) involucroos.listdir


    def listdir(path):
        """List directory contents, using cache."""
        try:
            cached_mtime, list = cache[path]
            del cache[path]
        except KeyError:
            cached_mtime, list = -1, []
        mtime = os.stat(path).st_mtime
        if mtime != cached_mtime:
            list = os.listdir(path)
            list.sort()
        cache[path] = mtime, list
        return list
    


  1. [man]: OPENDIR (3) / [man]: READDIR (3) / [man]: CLOSEDIR (3) tramite [Python]: ctypes - Una libreria di funzioni straniere per Python ( !!! Ux specifico !!! )

    ctypes è una libreria di funzioni straniere per Python. Fornisce tipi di dati compatibili con C e consente di chiamare funzioni in DLL o librerie condivise. Può essere usato per avvolgere queste librerie in puro Python.

    code_ctypes.py :

    #!/usr/bin/env python3
    
    import sys
    from ctypes import Structure, \
        c_ulonglong, c_longlong, c_ushort, c_ubyte, c_char, c_int, \
        CDLL, POINTER, \
        create_string_buffer, get_errno, set_errno, cast, sizeof
    
    
    DT_DIR = 4
    DT_REG = 8
    
    char256 = c_char * 256
    
    class LinuxDirent64(Structure):
        _fields_ = [
            ("d_ino", c_ulonglong),
            ("d_off", c_longlong),
            ("d_reclen", c_ushort),
            ("d_type", c_ubyte),
            ("d_name", char256),
        ]
    
    LinuxDirent64Ptr = POINTER(LinuxDirent64)
    
    libc_dll = CDLL(None)
    opendir = libc_dll.opendir
    readdir = libc_dll.readdir
    closedir = libc_dll.closedir
    libc_dll.__errno_location.restype = POINTER(c_int)
    errno_loc_func = libc_dll.__errno_location
    
    
    def _get_errno():
        return "errno: {:d}({:d})".format(get_errno(), errno_loc_func().contents.value)
    
    
    def get_dir_content(path):
        ret = [path, list(), list()]
        dir_stream = opendir(create_string_buffer(path.encode()))
        if (dir_stream == 0):
            print("opendir returned NULL ({:s})".format(_get_errno()))
            return ret
        set_errno(0)
        dirent_addr = readdir(dir_stream)
        while dirent_addr:
            dirent_ptr = cast(dirent_addr, LinuxDirent64Ptr)
            dirent = dirent_ptr.contents
            name = dirent.d_name.decode()
            if dirent.d_type & DT_DIR:
                if name not in (".", ".."):
                    ret[1].append(name)
            elif dirent.d_type & DT_REG:
                ret[2].append(name)
            dirent_addr = readdir(dir_stream)
        if get_errno() or errno_loc_func().contents.value:
            print("readdir returned NULL ({:s})".format(_get_errno()))
        closedir(dir_stream)
        return ret
    
    
    def main():
        print("{:s} on {:s}\n".format(sys.version, sys.platform))
        root_dir = "root_dir"
        entries = get_dir_content(root_dir)
        print(entries)
    
    
    if __name__ == "__main__":
        main()
    

    Note :

    • Carica le tre funzioni da libc (caricate nel processo corrente) e le chiama (per maggiori dettagli controlla []: Come faccio a verificare se esiste un file usando Python? (Risposta di @ CristiFati) - ultime note dall'articolo 4 . ). Ciò posizionerebbe questo approccio molto vicino al bordo Python / C
    • LinuxDirent64è la rappresentazione di ctypesstruct dirent64 da dirent.h (così come le DT_*costanti) dalla mia macchina: Ubtu 16 x64 ( 4.10.0-40-generic e libc6-dev: amd64 ). Su altri sapori / versioni, la definizione struct potrebbe differire, e in caso affermativo, le ctypes alias devono essere aggiornati, altrimenti si produrrà un comportamento indefinito
    • errno_loc_func(e tutto ciò che riguarda ad esso) è perché le funzioni impostate errnoin caso di errore, e ho bisogno di controllare il suo valore. Apparentemente, get_errnonon funziona (con un nome non valido, opendirrestituisce NULL, ma get_errnorestituisce ancora 0), o non l'ho ancora capito
    • Restituisce i dati nel os.walkformato 's. Non mi sono preoccupato di renderlo ricorsivo, ma partendo dal codice esistente, sarebbe un compito abbastanza banale
    • Tutto è fattibile anche su Win , i dati (librerie, funzioni, strutture, costanti, ...) differiscono


    Uscita :

    [email protected]:~/work//q003207219$ ./code_ctypes.py
    3.5.2 (default, Nov 23 2017, 16:37:01)
    [GCC 5.4.0 20160609] on linux
    
    ['root_dir', ['dir3', 'dir2', 'dir0', 'dir1'], ['file0', 'file1']]
    


  1. [ActiveState]: win32file.FindFilesW ( !!! Win specifico !!! )

    Recupera un elenco di nomi file corrispondenti, utilizzando l'API Unicode di Windows. Un'interfaccia all'API FindFirstFileW / FindNextFileW / Trova le funzioni di chiusura.


    >>> import os, win32file, win32con
    >>> root_dir = "root_dir"
    >>> wildcard = "*"
    >>> root_dir_wildcard = os.path.join(root_dir, wildcard)
    >>> entry_list = win32file.FindFilesW(root_dir_wildcard)
    >>> len(entry_list)  # Don't display the whole content as it's too long
    8
    >>> [entry[-2] for entry in entry_list]  # Only display the entry names
    ['.', '..', 'dir0', 'dir1', 'dir2', 'dir3', 'file0', 'file1']
    >>>
    >>> [entry[-2] for entry in entry_list if entry[0] & win32con.FILE_ATTRIBUTE_DIRECTORY and entry[-2] not in (".", "..")]  # Filter entries and only display dir names (except self and parent)
    ['dir0', 'dir1', 'dir2', 'dir3']
    >>>
    >>> [os.path.join(root_dir, entry[-2]) for entry in entry_list if entry[0] & (win32con.FILE_ATTRIBUTE_NORMAL | win32con.FILE_ATTRIBUTE_ARCHIVE)]  # Only display file "full" names
    ['root_dir\\file0', 'root_dir\\file1']
    

    Note :


  1. Installa alcuni (altri) pacchetti di terze parti che fanno il trucco
    • Molto probabilmente, si baserà su uno (o più) dei precedenti (magari con lievi personalizzazioni)


Note (circa le cose di cui sopra):

  • Il codice è pensato per essere portabile (tranne i luoghi che hanno come target un'area specifica - che sono contrassegnati) o incrociati:
    • piattaforma ( Ux , Win ,)
    • Versione Python (2, 3,)
  • Stili di percorso multipli (assoluto, parenti) sono stati utilizzati attraverso le varianti di cui sopra, per illustrare il fatto che gli "strumenti" utilizzati sono flessibili in questa direzione
  • os.listdire os.scandirutilizzare opendir/ readdir/ closedir( [MSDN]: funzione FindFirstFile / [MSDN]: funzione FindNextFile / [MSDN]: funzione FindClose ) (tramite " $ {PYTHON_SRC_DIR} /Modules/posixmodule.c ")
  • win32file.FindFilesWusa anche quelle ( specifiche per Win ) (tramite " $ {PYWIN32_SRC_DIR} /win32/src/win32file.i ")
  • get_dir_content(dal punto # 1. ) può essere implementato utilizzando uno qualsiasi di questi approcci (alcuni richiedono più lavoro e altri meno)
    • Alcuni filtri avanzati (invece che solo file vs. dir) potrebbero essere fatti: ad esempio l' include_foldersargomento potrebbe essere sostituito da un altro (es. filter_func) Che sarebbe una funzione che accetta un percorso come argomento: filter_func=lambda x: True(questo non esclude nulla) e dentro get_dir_contentqualcosa di simile: if not filter_func(entry_with_path): continue(se la funzione fallisce per una voce, verrà saltata), ma più il codice diventa complesso, più tempo ci vorrà per eseguire
  • Nota bene! Poiché si utilizza la ricorsione, devo menzionare che ho eseguito alcuni test sul mio laptop ( Win 10 x64 ), totalmente estraneo a questo problema, e quando il livello di ricorsione stava raggiungendo valori nell'intervallo (990 .. 1000) (limite di ricorsione - 1000 (predefinito)), ho ottenuto :). Se l'albero delle directory supera questo limite (non sono un esperto di FS , quindi non so se è possibile), potrebbe essere un problema.
    Devo anche dire che non ho provato ad aumentare la ricorsione perché non ho esperienza nell'area (quanto posso aumentarla prima di dover aumentare anche lo stack al SOlivello), ma in teoria ci sarà sempre la possibilità di fallimento, se la profondità di dir è maggiore del massimo possibile di ricorsione (su quella macchina)
  • I campioni di codice sono solo a scopo dimostrativo. Ciò significa che non ho preso in considerazione la gestione degli errori (non penso ci sia un blocco try/ except/ else/ finally), quindi il codice non è robusto (il motivo è: mantenerlo il più semplice e breve possibile). Per la produzione , dovrebbe essere aggiunta anche la gestione degli errori

Fine della prima parte 1


1. A causa del fatto che il limite di post (domanda / risposta) di Home è di 30000 caratteri ( [SE.Meta]: Conoscere i tuoi limiti: qual è la lunghezza massima di un titolo di domanda, post, immagine e link utilizzati? ), la risposta è stata divisa in 2 parti. Per favore visita anche [SO]: Come elenco tutti i file di una directory? (@ Risposta di CristiFati - "Seconda parte") .


Dalla versione 3.4 ci sono gli iteratori integrati per questo che sono molto più efficienti di os.listdir() :

pathlib : Novità nella versione 3.4.

>>> import pathlib
>>> [p for p in pathlib.Path('.').iterdir() if p.is_file()]

Secondo PEP 428 , lo scopo della libreria pathlib è di fornire una semplice gerarchia di classi per gestire i percorsi del filesystem e le operazioni comuni che gli utenti eseguono su di essi.

os.scandir() : nuovo nella versione 3.5.

>>> import os
>>> [entry for entry in os.scandir('.') if entry.is_file()]

Si noti che os.walk() utilizza os.scandir() posto di os.listdir() dalla versione 3.5 e la sua velocità è aumentata di 2-20 volte secondo PEP 471 .

Consentitemi anche di leggere il commento di ShadowRanger qui sotto.


Dovresti usare il modulo os per elencare il contenuto della directory. os.listdir(".") restituisce tutti i contenuti della directory. Ripetiamo il risultato e aggiungiamo alla lista.

import os

content_list = []

for content in os.listdir("."): # "." means current directory
    content_list.append(content)

print content_list

Preferisco usare il modulo glob , in quanto esegue la corrispondenza e l'espansione dei pattern.

import glob
print(glob.glob("/home/adam/*.txt"))

Restituirà una lista con i file interrogati:

['/home/adam/file1.txt', '/home/adam/file2.txt', .... ]

Una soluzione a una riga per ottenere solo l'elenco dei file (senza sottodirectory):

filenames = next(os.walk(path))[2]

o percorsi assoluti:

paths = [os.path.join(path,fn) for fn in next(os.walk(path))[2]]

Ottenere percorsi di file completi da una directory e da tutte le sue sottodirectory

import os

def get_filepaths(directory):
    """
    This function will generate the file names in a directory 
    tree by walking the tree either top-down or bottom-up. For each 
    directory in the tree rooted at directory top (including top itself), 
    it yields a 3-tuple (dirpath, dirnames, filenames).
    """
    file_paths = []  # List which will store all of the full filepaths.

    # Walk the tree.
    for root, directories, files in os.walk(directory):
        for filename in files:
            # Join the two strings in order to form the full filepath.
            filepath = os.path.join(root, filename)
            file_paths.append(filepath)  # Add it to the list.

    return file_paths  # Self-explanatory.

# Run the above function and store its results in a variable.   
full_file_paths = get_filepaths("/Users/johnny/Desktop/TEST")
  • Il percorso che ho fornito nella funzione precedente conteneva 3 file, due dei quali nella directory principale e un altro in una sottocartella chiamata "SUBFOLDER". Ora puoi fare cose come:
  • print full_file_paths che stamperà la lista:

    • ['/Users/johnny/Desktop/TEST/file1.txt', '/Users/johnny/Desktop/TEST/file2.txt', '/Users/johnny/Desktop/TEST/SUBFOLDER/file3.dat']

Se lo desideri, puoi aprire e leggere il contenuto oppure concentrarti solo sui file con estensione ".dat" come nel seguente codice:

for f in full_file_paths:
  if f.endswith(".dat"):
    print f

/Users/johnny/Desktop/TEST/SUBFOLDER/file3.dat


Restituire un elenco di percorsi di file assoluti, non ricorre nelle sottodirectory

L = [os.path.join(os.getcwd(),f) for f in os.listdir('.') if os.path.isfile(os.path.join(os.getcwd(),f))]

Esegui findfiles () con una directory come parametro e restituirà un elenco di tutti i file al suo interno.

import os
def findfiles(directory):
    objects = os.listdir(directory)  # find all objects in a dir

    files = []
    for i in objects:  # check if very object in the folder ...
        if os.path.isfile(os.path.join(directory, i)):  # ... is a file.
            files.append(i)  # if yes, append it.
    return files

Un'altra variante molto leggibile per Python 3.4+ sta usando pathlib.Path.glob:

from pathlib import Path
folder = '/foo'
[f for f in Path(folder).glob('*') if f.is_file()]

È semplice rendere più specifici, ad esempio cercare solo i file di origine Python che non sono link simbolici, anche in tutte le sottodirectory:

[f for f in Path(folder).glob('**/*.py') if not f.is_symlink()]

Utilizzare questa funzione se si desidera utilizzare un tipo di file diverso o ottenere la directory completa:

import os

def createList(foldername, fulldir = True, suffix=".jpg"):
    file_list_tmp = os.listdir(foldername)
    #print len(file_list_tmp)
    file_list = []
    if fulldir:
        for item in file_list_tmp:
            if item.endswith(suffix):
                file_list.append(os.path.join(foldername, item))
    else:
        for item in file_list_tmp:
            if item.endswith(suffix):
                file_list.append(item)
    return file_list

Versione davvero semplice:

import os
[f for f in os.listdir(os.getcwd) if ...]

Fornirò un campione di un liner in cui l'origine e il tipo di file possono essere forniti come input. Il codice restituisce un elenco di nomi di file con estensione csv. Usa . nel caso in cui tutti i file devono essere restituiti. Questo scriverà anche in modo ricorsivo le sottodirectory.

[y for x in os.walk(sourcePath) for y in glob(os.path.join(x[0], '*.csv'))]

Modifica le estensioni di file e il percorso di origine secondo necessità.


Python 3.5 ha introdotto un nuovo metodo più veloce per camminare nella directory - os.scandir().

Esempio:

for file in os.scandir('/usr/bin'):
    line = ''
    if file.is_file():
        line += 'f'
    elif file.is_dir():
        line += 'd'
    elif file.is_symlink():
        line += 'l'
    line += '\t'
    print("{}{}".format(line, file.name))

Se ti interessano le prestazioni, prova scandir. Per Python 2.x, potrebbe essere necessario installarlo manualmente. Esempi:

# python 2.x
import scandir
import sys

de = scandir.scandir(sys.argv[1])
while 1:
    try:
        d = de.next()
        print d.path
    except StopIteration as _:
        break

Ciò consente di risparmiare un sacco di tempo quando è necessario eseguire la scansione di una directory enorme e non è necessario eseguire il buffer di un elenco enorme, ma solo recuperarli uno alla volta. E anche tu puoi farlo in modo ricorsivo:

def scan_path(path):
    de = scandir.scandir(path)
    while 1:
        try:
            e = de.next()
            if e.is_dir():
                scan_path(e.path)
            else:
                print e.path
        except StopIteration as _:
                break

Utilizzando la oslibreria.

import os
for root, dirs,files in os.walk("your dir path", topdown=True):
    for name in files:
        print(os.path.join(root, name))

def list_files(path):
    # returns a list of names (with extension, without full path) of all files 
    # in folder path
    files = []
    for name in os.listdir(path):
        if os.path.isfile(os.path.join(path, name)):
            files.append(name)
    return files 

import dircache
list = dircache.listdir(pathname)
i = 0
check = len(list[0])
temp = []
count = len(list)
while count != 0:
  if len(list[i]) != check:
     temp.append(list[i-1])
     check = len(list[i])
  else:
    i = i + 1
    count = count - 1

print temp

import os
lst=os.listdir(path)

os.listdir restituisce una lista contenente i nomi delle voci nella directory data dal percorso.


import os
os.listdir("somedirectory")

restituirà un elenco di tutti i file e le directory in "somedirectory".





directory