Hoe maak ik een lijst van alle bestanden van een map?

Hoe kan ik alle bestanden van een directory in Python weergeven en aan een list toevoegen?


Antwoord 1, autoriteit 100%

os.listdir() haalt alles uit een directory – bestanden en directories.

Als u slechts bestanden wilt, kunt u dit filteren met os.path:

from os import listdir
from os.path import isfile, join
onlyfiles = [f for f in listdir(mypath) if isfile(join(mypath, f))]

of je kunt gebruiken os.walk() die twee lijsten oplevert voor elke bezochte map – opgesplitst in bestanden en dirs voor jou. Als u alleen de bovenste map wilt, kunt u deze de eerste keer breken

from os import walk
f = []
for (dirpath, dirnames, filenames) in walk(mypath):
    f.extend(filenames)
    break

of, korter:

from os import walk
filenames = next(walk(mypath), (None, None, []))[2]  # [] if no file

Antwoord 2, autoriteit 39%

Ik gebruik liever de module glob omdat doet patroonafstemming en uitbreiding.

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

Het past intuïtief patronen aan

import glob
# All files ending with .txt
print(glob.glob("/home/adam/*.txt")) 
# All files ending with .txt with depth of 2 folder
print(glob.glob("/home/adam/*/*.txt")) 

Het geeft een lijst terug met de opgevraagde bestanden:

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

Antwoord 3, autoriteit 24%

os.listdir() – lijst in de huidige map

Met listdir in os module krijg je de bestanden en mappen in de huidige dir

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

Zoeken in een directory

arr = os.listdir('c:\\files')

glob van glob

met glob kun je een type bestand specificeren om op deze manier weer te geven

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

glob in een lijst begrip

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

haal het volledige pad van alleen bestanden in de huidige map

import os
from os import listdir
from os.path import isfile, join
cwd = os.getcwd()
onlyfiles = [os.path.join(cwd, f) for f in os.listdir(cwd) if 
os.path.isfile(os.path.join(cwd, f))]
print(onlyfiles) 
['G:\\getfilesname\\getfilesname.py', 'G:\\getfilesname\\example.txt']

De volledige padnaam ophalen met os.path.abspath

Je krijgt er het volledige pad voor terug

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

Wandelen: door submappen gaan

os.walk retourneert de root, de directorylijst en de bestandenlijst, daarom heb ik ze uitgepakt in r, d, f in de for-lus; het zoekt dan naar andere bestanden en mappen in de submappen van de root enzovoort totdat er geen submappen zijn.

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 file.endswith(".docx"):
            print(os.path.join(r, file))

os.listdir(): haal bestanden op in de huidige map (Python 2)

Als u in Python 2 de lijst met bestanden in de huidige map wilt, moet u het argument ‘.’ of os.getcwd() in de os.listdir methode.

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

Om omhoog te gaan in de mappenboom

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

Bestanden ophalen: os.listdir() in een bepaalde map (Python 2 en 3)

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

Bestanden van een bepaalde submap ophalen met os.listdir()

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

os.walk('.') – huidige map

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

next(os.walk('.')) en 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)
>>> F:\\_python\\dict_class.py
>>> F:\\_python\\programmi.txt

next(os.walk('F:\\') – verkrijg het volledige pad – lijst begrip

 [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 – krijg volledig pad – alle bestanden in submap**

x = [os.path.join(r,file) for r,d,f in os.walk("F:\\_python") for file in f]
print(x)
>>> ['F:\\_python\\dict.py', 'F:\\_python\\progr.txt', 'F:\\_python\\readl.py']

os.listdir() – krijg alleen txt-bestanden

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

glob gebruiken om het volledige pad van de bestanden te krijgen

Als ik het absolute pad van de bestanden nodig heb:

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

os.path.isfile gebruiken om mappen in de lijst te vermijden

import os.path
listOfFiles = [f for f in os.listdir() if os.path.isfile(f)]
print(listOfFiles)
>>> ['a simple game.py', 'data.txt', 'decorator.py']

pathlib gebruiken uit 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

Met list comprehension:

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

U kunt ook pathlib.Path() gebruiken in plaats van pathlib.Path(".")

Gebruik glob-methode in pathlib.Path()

import pathlib
py = pathlib.Path().glob("*.py")
for file in py:
    print(file)
>>> stack_overflow_list.py
>>> stack_overflow_list_tkinter.py

Alle en alleen bestanden ophalen met os.walk

import os
x = [i[2] for i in os.walk('.')]
y=[]
for t in x:
    for f in t:
        y.append(f)
print(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']

Alleen bestanden ophalen met next en walk in een directory

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

Alleen mappen met volgende en loop in een map

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

Verkrijg alle submapnamen met 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() van Python 3.5 en hoger

import os
x = [f.name for f in os.scandir() if f.is_file()]
print(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

Voorbeelden:

Bijv. 1: Hoeveel bestanden zijn er in de submappen?

In dit voorbeeld zoeken we naar het aantal bestanden dat in alle directory’s en zijn subdirectories is opgenomen.

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"))
>>> 'F:\\\python' : 12057 files'

Voorbeeld 2: Hoe kopieer ik alle bestanden van een map naar een andere?

Een script om orde te scheppen op uw computer om alle bestanden van een type (standaard: pptx) te vinden en ze naar een nieuwe map te kopiëren.

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('-' * 30)
        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')
>>> _compiti18\Compito Contabilita 1\conti.txt
>>> _compiti18\Compito Contabilita 1\modula4.txt
>>> _compiti18\Compito Contabilita 1\moduloa4.txt
>>> ------------------------
>>> ==> Found in: `_compiti18` : 3 files

Bijv. 3: Hoe alle bestanden in een txt-bestand te krijgen

Als u een txt-bestand wilt maken met alle bestandsnamen:

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

Voorbeeld: txt met alle bestanden van een harde schijf

"""
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")

Alle bestanden van C:\ in één tekstbestand

Dit is een kortere versie van de vorige code. Wijzig de map waar u de bestanden wilt zoeken als u vanaf een andere positie moet beginnen. Deze code genereert een tekstbestand van 50 mb op mijn computer met iets minder dan 500.000 regels met bestanden met het volledige pad.

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")

Hoe schrijf je een bestand met alle paden in een map van een type

Met deze functie kunt u een txt-bestand maken met de naam van een type bestand dat u zoekt (bijv. pngfile.txt) met het volledige pad van alle bestanden van dat type. Het kan soms handig zijn, denk ik.

import os
def searchfiles(extension='.ttf', folder='H:\\'):
    "Create a txt file with all the file of a type"
    with open(extension[1:] + "file.txt", "w", encoding="utf-8") as filewrite:
        for r, d, f in os.walk(folder):
            for file in f:
                if file.endswith(extension):
                    filewrite.write(f"{r + file}\n")
# looking for png file (fonts) in the hard disk H:\
searchfiles('.png', 'H:\\')
>>> H:\4bs_18\Dolphins5.png
>>> H:\4bs_18\Dolphins6.png
>>> H:\4bs_18\Dolphins7.png
>>> H:\5_18\marketing html\assets\imageslogo2.png
>>> H:\7z001.png
>>> H:\7z002.png

(Nieuw) Vind alle bestanden en open ze met tkinter GUI

Ik wilde in deze 2019 een kleine app toevoegen om naar alle bestanden in een map te zoeken en ze te kunnen openen door te dubbelklikken op de naam van het bestand in de lijst.
voer hier de afbeeldingsbeschrijving in

import tkinter as tk
import os
def searchfiles(extension='.txt', folder='H:\\'):
    "insert all files in the listbox"
    for r, d, f in os.walk(folder):
        for file in f:
            if file.endswith(extension):
                lb.insert(0, r + "\\" + file)
def open_file():
    os.startfile(lb.get(lb.curselection()[0]))
root = tk.Tk()
root.geometry("400x400")
bt = tk.Button(root, text="Search", command=lambda:searchfiles('.png', 'H:\\'))
bt.pack()
lb = tk.Listbox(root)
lb.pack(fill="both", expand=1)
lb.bind("<Double-Button>", lambda x: open_file())
root.mainloop()

Antwoord 4, autoriteit 17%

import os
os.listdir("somedirectory")

retourneert een lijst van alle bestanden en mappen in “somedirectory”.


Antwoord 5, autoriteit 3%

Een éénregelige oplossing om alleen een lijst met bestanden te krijgen (geen submappen):

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

of absolute padnamen:

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

Antwoord 6, autoriteit 3%

Volledige bestandspaden ophalen uit een map en al zijn submappen

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")

  • Het pad dat ik in de bovenstaande functie heb opgegeven, bevatte drie bestanden twee ervan in de hoofdmap en een andere in een submap met de naam “SUBFOLDER”. Je kunt nu dingen doen als:
  • print full_file_paths waarmee de lijst wordt afgedrukt:

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

Als je wilt, kun je de inhoud openen en lezen, of je alleen richten op bestanden met de extensie “.dat”, zoals in de onderstaande code:

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

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


Antwoord 7, autoriteit 2%

Sinds versie 3.4 zijn hiervoor ingebouwde iterators die een stuk efficiënter zijn dan os.listdir():

pathlib: Nieuw in versie 3.4.

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

Volgens PEP 428 is het doel van de pathlib bibliotheek is om een ​​eenvoudige hiërarchie van klassen te bieden om bestandssysteempaden te verwerken en de algemene handelingen die gebruikers erover doen.

os.scandir(): Nieuw in versie 3.5.

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

Merk op dat os.walk() gebruikt os.scandir() in plaats van os.listdir() van versie 3.5, en de snelheid is 2-20 keer verhoogd volgens PEP 471.

Laat me je ook aanraden om de onderstaande opmerking van ShadowRanger te lezen.


Antwoord 8

Inleidende opmerkingen

  • Hoewel er een duidelijk onderscheid is tussen de termen bestand en directory in de vraagtekst, kunnen sommigen beweren dat mappen eigenlijk speciale bestanden zijn
  • De verklaring: “alle bestanden van een map” kan op twee manieren worden geïnterpreteerd:
    1. Alle directe (of niveau 1) afstammelingen alleen
    2. Alle afstammelingen in de hele mappenboom (inclusief die in submappen)
  • Toen de vraag werd gesteld, stel ik me voor dat Python 2 de LTS-versie was, maar de codevoorbeelden zullen gerund door Python 3(.5) (ik zal ze zo houden als mogelijk Python 2; ook , elke code van Python die ik ga posten, is van v3.5.4 – tenzij anders aangegeven). Dat heeft gevolgen voor een ander zoekwoord in de vraag: “voeg ze toe aan een lijst“:

    • In pre-Python 2.2-versies werden reeksen (iterables) meestal weergegeven door lijsten (tupels, sets, …)
    • In Python 2.2, het concept van generator ([Python.Wiki]: generatoren) – met dank aan [Python 3]: Het rendementsoverzicht) – werd geïntroduceerd. Naarmate de tijd verstreek, begonnen generator-tegenhangers te verschijnen voor functies die terugkwamen van/werkten met lijsten
    • In Python 3 is generator het standaardgedrag
    • Ik weet niet zeker of het retourneren van een lijst nog steeds verplicht is (of een generator zou het ook doen), maar als een generator wordt doorgegeven aan de list-constructor, wordt er een lijst van gemaakt (en ook verbruikt ). Het onderstaande voorbeeld illustreert de verschillen op [Python 3]: kaart(functie, itereerbaar, …)
    >>> import sys
    >>> sys.version
    '2.7.10 (default, Mar  8 2016, 15:02:46) [MSC v.1600 64 bit (AMD64)]'
    >>> m = map(lambda x: x, [1, 2, 3])  # Just a dummy lambda function
    >>> m, type(m)
    ([1, 2, 3], <type 'list'>)
    >>> len(m)
    3
    

    >>> import sys
    >>> sys.version
    '3.5.4 (v3.5.4:3f56838, Aug  8 2017, 02:17:05) [MSC v.1900 64 bit (AMD64)]'
    >>> 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)  # Build a list from the generator
    >>> lm0, type(lm0)
    ([1, 2, 3], <class 'list'>)
    >>>
    >>> lm1 = list(m)  # Build a list from the same generator
    >>> lm1, type(lm1)  # Empty list now - generator already consumed
    ([], <class 'list'>)
    
  • De voorbeelden zijn gebaseerd op een map met de naam root_dir met de volgende structuur (dit voorbeeld is voor Win, maar ik gebruik dezelfde boom op Lnx ook):

    E:\Work\Dev\StackOverflow\q003207219>tree /f "root_dir"
    Folder PATH listing for volume Work
    Volume serial number is 00000029 3655:6FED
    E:\WORK\DEV\STACKOVERFLOW\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
    

Oplossingen

Programmatische benaderingen:

  1. [Python 3]: os.listdir (path=’.’)

    Retourneer een lijst met de namen van de items in de directory die door het pad is opgegeven. De lijst is in willekeurige volgorde en bevat niet de speciale vermeldingen '.' en '..'

    >>> 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 items and only keep files (strip out directories)
    ['file0', 'file1']
    

    Een uitgebreider voorbeeld (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()
    

    Opmerkingen:

    • Er zijn twee implementaties:
      • Een die generatoren gebruikt (natuurlijk lijkt het hier nutteloos, aangezien ik het resultaat onmiddellijk naar een lijst converteer)
      • De klassieke (functienamen eindigend op _old)
    • Recursie wordt gebruikt (om in submappen te komen)
    • Voor elke implementatie zijn er twee functies:
      • Eentje die begint met een underscore (_): “private” (mag niet direct worden aangeroepen) – dat doet al het werk
      • De openbare (omslag over vorige): het verwijdert gewoon het oorspronkelijke pad (indien nodig) van de geretourneerde items. Het is een lelijke implementatie, maar het is het enige idee dat ik op dit moment zou kunnen bedenken
    • In termen van prestaties zijn generatoren over het algemeen een beetje sneller (rekening houdend met zowel creatie als iteratie tijden), maar ik heb ze niet getest in recursieve functies, en ik ben ook aan het itereren in de functie over innerlijke generatoren – ik weet niet hoe prestatievriendelijk dat is
    • Speel met de argumenten om verschillende resultaten te krijgen

    Uitvoer:

    (py35x64_test) E:\Work\Dev\StackOverflow\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 3]: os.scandir (path=’.’) (Python 3.5+, backport: [PyPI]: scandir)

    Retourneer een iterator van os.DirEntry-objecten die overeenkomen met de vermeldingen in de directory gegeven door pad. De vermeldingen worden in willekeurige volgorde opgeleverd en de speciale vermeldingen '.' en '..' zijn niet inbegrepen.

    scandir() gebruiken in plaats van listdir() kan de prestaties van code die ook een bestandstype of bestand nodig heeft aanzienlijk verbeteren attribuutinformatie, omdat os.DirEntry-objecten deze informatie vrijgeven als de besturingssysteem biedt het bij het scannen van een map. Alle os.DirEntry-methoden kunnen een systeemaanroep uitvoeren, maar is_dir() en is_file() vereisen meestal alleen een systeemaanroep voor symbolische links; os.DirEntry.stat() vereist altijd een systeem oproep op Unix, maar vereist slechts één voor symbolische links op 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
    

    Opmerkingen:

    • Het lijkt op os.listdir
    • Maar het is ook flexibeler (en biedt meer functionaliteit), meer Pythonic (en in sommige gevallen sneller)

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

    Genereer de bestandsnamen in een mappenboom door de boom van boven naar beneden of van onder naar boven te doorlopen. Voor elke map in de boom die is geroot in map top (inclusief top zelf), levert dit een 3-tuple op (dirpath, dirnames, filenames).

    >>> import os
    >>> root_dir = os.path.join(os.getcwd(), "root_dir")  # Specify the full path
    >>> root_dir
    'E:\\Work\\Dev\\StackOverflow\\q003207219\\root_dir'
    >>>
    >>> walk_generator = os.walk(root_dir)
    >>> root_dir_entry = next(walk_generator)  # First entry corresponds to the root dir (passed as an argument)
    >>> root_dir_entry
    ('E:\\Work\\Dev\\StackOverflow\\q003207219\\root_dir', ['dir0', 'dir1', 'dir2', 'dir3'], ['file0', 'file1'])
    >>>
    >>> root_dir_entry[1] + root_dir_entry[2]  # Display dirs and files (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\\StackOverflow\\q003207219\\root_dir\\dir0', 'E:\\Work\\Dev\\StackOverflow\\q003207219\\root_dir\\dir1', 'E:\\Work\\Dev\\StackOverflow\\q003207219\\root_dir\\dir2', 'E:\\Work\\Dev\\StackOverflow\\q003207219\\root_dir\\dir3', 'E:\\Work\\Dev\\StackOverflow\\q003207219\\root_dir\\file0', 'E:\\Work\\Dev\\StackOverflow\\q003207219\\root_dir\\file1']
    >>>
    >>> for entry in walk_generator:  # Display the rest of the elements (corresponding to every subdir)
    ...     print(entry)
    ...
    ('E:\\Work\\Dev\\StackOverflow\\q003207219\\root_dir\\dir0', ['dir00', 'dir01', 'dir02'], [])
    ('E:\\Work\\Dev\\StackOverflow\\q003207219\\root_dir\\dir0\\dir00', ['dir000'], ['file000'])
    ('E:\\Work\\Dev\\StackOverflow\\q003207219\\root_dir\\dir0\\dir00\\dir000', [], ['file0000'])
    ('E:\\Work\\Dev\\StackOverflow\\q003207219\\root_dir\\dir0\\dir01', [], ['file010', 'file011'])
    ('E:\\Work\\Dev\\StackOverflow\\q003207219\\root_dir\\dir0\\dir02', ['dir020'], [])
    ('E:\\Work\\Dev\\StackOverflow\\q003207219\\root_dir\\dir0\\dir02\\dir020', ['dir0200'], [])
    ('E:\\Work\\Dev\\StackOverflow\\q003207219\\root_dir\\dir0\\dir02\\dir020\\dir0200', [], [])
    ('E:\\Work\\Dev\\StackOverflow\\q003207219\\root_dir\\dir1', [], ['file10', 'file11', 'file12'])
    ('E:\\Work\\Dev\\StackOverflow\\q003207219\\root_dir\\dir2', ['dir20'], ['file20'])
    ('E:\\Work\\Dev\\StackOverflow\\q003207219\\root_dir\\dir2\\dir20', [], ['file200'])
    ('E:\\Work\\Dev\\StackOverflow\\q003207219\\root_dir\\dir3', [], [])
    

    Opmerkingen:

    • Onder de schermen gebruikt het os.scandir (os.listdir op oudere versies)
    • Het doet het zware werk door terug te keren in submappen

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

    Retourneer een mogelijk lege lijst met padnamen die overeenkomen met padnaam, die een tekenreeks moet zijn die een padspecificatie bevat. padnaam kan absoluut zijn (zoals /usr/src/Python-1.5/Makefile) of relatief (zoals ../../Tools/*/*.gif), en kan jokertekens in shell-stijl bevatten. Gebroken symbolische links zijn opgenomen in de resultaten (zoals in de shell).

    Gewijzigd in versie 3.5: Ondersteuning voor recursieve globs met ** .

    >>> 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
    

    Opmerkingen:

    • Gebruikt os.listdir
    • Voor grote bomen (vooral als recursief is ingeschakeld), heeft iglob de voorkeur
    • Staat geavanceerde filtering toe op naam (vanwege de wildcard)

  1. [Python 3]: klasse pathlib. Pad(*pathsegments) (Python 3.4+, backport: [PyPI]: pathlib2)

    >>> 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']
    

    Opmerkingen:

    • Dit is een manier om ons doel te bereiken
    • Het is de OOP-stijl voor het afhandelen van paden
    • Biedt veel functionaliteiten

  1. [Python 2]: dircache.listdir(pad) (alleen Python 2)

    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. [man7]: OPENDIR(3) / [man7]: READDIR(3) / [man7]: CLOSEDIR(3) via [Python 3]: ctypes – Een buitenlandse functiebibliotheek voor Python (POSIX specifiek)

    ctypes is een buitenlandse functiebibliotheek voor Python. Het biedt C-compatibele gegevenstypen en maakt aanroepfuncties in DLL’s of gedeelde bibliotheken mogelijk. Het kan worden gebruikt om deze bibliotheken in pure Python te verpakken.

    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
    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 = this_process = CDLL(None, use_errno=True)
    # ALWAYS set argtypes and restype for functions, otherwise it's UB!!!
    opendir = libc_dll.opendir
    readdir = libc_dll.readdir
    closedir = libc_dll.closedir
    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 (errno: {:d})".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():
            print("readdir returned NULL (errno: {:d})".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()
    

    Opmerkingen:

    • Het laadt de drie functies van libc (geladen in het huidige proces) en roept ze aan (check voor meer details [SO]: Hoe controleer ik of een bestand bestaat zonder uitzonderingen? (@CristiFati’s antwoord) – laatste notities van item #4.). Dat zou deze benadering heel dicht bij de Python / C-rand
    • plaatsen

    • LinuxDirent64 is de ctypes-representatie van struct dirent64 van [man7]: dirent.h(0P) (net als de DT_ constanten) van mijn machine: Ubtu 16 x64 (4.10.0-40-generiek en libc6-dev:amd64). Bij andere smaken/versies kan de structdefinitie verschillen, en als dat zo is, moet de alias ctypes worden bijgewerkt, anders levert het Undefined Behaviour
    • op

    • Het retourneert gegevens in de indeling van os.walk. Ik heb niet de moeite genomen om het recursief te maken, maar uitgaande van de bestaande code zou dat een vrij triviale taak zijn
    • Alles is ook mogelijk op Win, de gegevens (bibliotheken, functies, structs, constanten, …) verschillen

    Uitvoer:

    [[email protected]:~/Work/Dev/StackOverflow/q003207219]> ./code_ctypes.py
    3.5.2 (default, Nov 12 2018, 13:43:14)
    [GCC 5.4.0 20160609] on linux
    ['root_dir', ['dir2', 'dir1', 'dir3', 'dir0'], ['file1', 'file0']]
    

  1. [ActiveState.Docs]: win32file.FindFilesW (Win specifiek)

    Haalt een lijst met overeenkomende bestandsnamen op met behulp van de Windows Unicode API. Een interface naar de API FindFirstFileW/FindNextFileW/Find sluitfuncties.

    >>> 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']
    

    Opmerkingen:

  1. Installeer een (ander) pakket van derden dat het lukt
    • Hoogstwaarschijnlijk zal vertrouwen op een (of meer) van de bovenstaande (misschien met kleine aanpassingen)

Opmerkingen:

  • Code is bedoeld om overdraagbaar te zijn (behalve plaatsen die gericht zijn op een specifiek gebied – die zijn gemarkeerd) of kruisen:

    • platform (Nix, Win, )
    • Python-versie (2, 3, )
  • Meerdere padstijlen (absoluut, verwanten) werden gebruikt in de bovenstaande varianten, om te illustreren dat de gebruikte “tools” flexibel zijn in deze richting

  • os.listdir en os.scandir gebruiken opendir / readdir / closedir ([MS.Docs]: FindFirstFileW-functie / [MS.Docs ]: FindNextFileW-functie / [MS .Docs]: FindClose-functie) (via [GitHub]: python/cpython – (master) cpython/Modules/posixmodule.c)

  • win32file.FindFilesW gebruikt deze (Win-specifieke) functies ook (via [GitHub]: mhammond/pywin32 – (master) pywin32/win32/src/win32file.i)

  • _get_dir_content (vanaf punt #1.) kan worden geïmplementeerd met elk van deze benaderingen (sommige zullen meer werk vergen en wat minder)

    • Enige geavanceerde filtering (in plaats van alleen bestand vs. dir) kan worden gedaan: b.v. het argument include_folders zou kunnen worden vervangen door een ander argument (bijv. filter_func), wat een functie zou zijn die een pad als argument moet aannemen: filter_func=lambda x: True (dit verwijdert niets) en binnen _get_dir_content zoiets als: if not filter_func(entry_with_path): continue (als de functie faalt voor één item, worden overgeslagen), maar hoe complexer de code wordt, hoe langer het duurt om uit te voeren
  • Nota bene! Aangezien recursie wordt gebruikt, moet ik vermelden dat ik enkele tests op mijn laptop heb gedaan (Win 10 x64), die totaal niets met dit probleem te maken hebben , en toen het recursieniveau waarden bereikte ergens in het (990 .. 1000) bereik (recursionlimit – 1000 (standaard)), kreeg ik StackOverflow em> :). Als de directorystructuur die limiet overschrijdt (ik ben geen FS-expert, dus ik weet niet of dat zelfs mogelijk is), zou dat een probleem kunnen zijn.
    Ik moet ook vermelden dat ik niet heb geprobeerd de recursielimiet te verhogen omdat ik geen ervaring op dit gebied heb (hoeveel kan ik het verhogen voordat ik ook de stapel op OS niveau), maar in theorie zal er altijd een kans op mislukking zijn, als de dir-diepte groter is dan de hoogst mogelijke recursielimiet (op die machine)

  • De codevoorbeelden zijn alleen voor demonstratieve doeleinden. Dat betekent dat ik geen rekening heb gehouden met foutafhandeling (ik denk niet dat er een probeer / behalve / else / eindelijk blok), dus de code is niet robuust (de reden is: om hem te behouden zo eenvoudig en kort mogelijk). Voor productie moet ook foutafhandeling worden toegevoegd

Andere benaderingen:

  1. Gebruik Python alleen als een wrapper

    • Alles wordt gedaan met een andere technologie
    • Die technologie wordt aangeroepen door Python
    • De meest bekende smaak die ik ken, is wat ik de systeembeheerder-aanpak noem:

      • Gebruik Python (of welke programmeertaal dan ook) om shell-opdrachten uit te voeren (en hun uitvoer te ontleden)
      • Sommigen beschouwen dit als een nette hack
      • Ik beschouw het meer als een slappe oplossing (gainarie), aangezien de actie op zich wordt uitgevoerd vanuit shell (cmd in dit geval ), en heeft dus niets te maken met Python.
      • Filteren (grep / findstr) of uitvoerformattering kan aan beide kanten worden gedaan, maar ik ga er niet op aandringen. Ook heb ik bewust os.system gebruikt in plaats van subprocess.Popen.
      (py35x64_test) E:\Work\Dev\StackOverflow\q003207219>"e:\Work\Dev\VEnvs\py35x64_test\Scripts\python.exe" -c "import os;os.system(\"dir /b root_dir\")"
      dir0
      dir1
      dir2
      dir3
      file0
      file1
      

    In het algemeen moet deze benadering worden vermeden, aangezien als een uitvoerformaat van een opdracht enigszins verschilt tussen versies/smaken van OS, de parseercode ook moet worden aangepast; om nog maar te zwijgen van de verschillen tussen landen).


Antwoord 9

Ik vond het antwoord van adamk’s antwoord erg leuk, waarbij ik voorstelde dat je glob() uit de gelijknamige module. Dit stelt je in staat om patronen te matchen met *s.

Maar zoals andere mensen in de opmerkingen hebben opgemerkt, kan glob() struikelen over inconsistente schuine strepen. Om daarbij te helpen, raad ik u aan de functies join() en expanduser() in de module os.path te gebruiken, en misschien de getcwd() functie ook in de os module.

Als voorbeelden:

from glob import glob
# Return everything under C:\Users\admin that contains a folder called wlp.
glob('C:\Users\admin\*\wlp')

Het bovenstaande is verschrikkelijk – het pad is hard gecodeerd en zal alleen werken op Windows tussen de schijfnaam en de \s die hardgecodeerd zijn in het pad.

from glob    import glob
from os.path import join
# Return everything under Users, admin, that contains a folder called wlp.
glob(join('Users', 'admin', '*', 'wlp'))

Het bovenstaande werkt beter, maar het is afhankelijk van de mapnaam Users die vaak wordt gevonden op Windows en niet zo vaak op andere besturingssystemen. Het is ook afhankelijk van de gebruiker die een specifieke naam heeft, admin.

from glob    import glob
from os.path import expanduser, join
# Return everything under the user directory that contains a folder called wlp.
glob(join(expanduser('~'), '*', 'wlp'))

Dit werkt perfect op alle platforms.

Nog een geweldig voorbeeld dat perfect werkt op verschillende platforms en iets anders doet:

from glob    import glob
from os      import getcwd
from os.path import join
# Return everything under the current directory that contains a folder called wlp.
glob(join(getcwd(), '*', 'wlp'))

Ik hoop dat deze voorbeelden je helpen de kracht te zien van enkele van de functies die je kunt vinden in de standaard Python-bibliotheekmodules.


Antwoord 10

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 

Antwoord 11

Als je op zoek bent naar een Python-implementatie van find, dan is dit een recept dat ik vrij vaak gebruik:

from findtools.find_files import (find_files, Match)
# Recursively find all *.sh files in **/usr/bin**
sh_files_pattern = Match(filetype='f', name='*.sh')
found_files = find_files(path='/usr/bin', match=sh_files_pattern)
for found_file in found_files:
    print found_file

Dus ik heb er een PyPI pakket van gemaakt en er is ook een GitHub-repository. Ik hoop dat iemand het potentieel nuttig vindt voor deze code.


Antwoord 12

Voor betere resultaten kun je de listdir() methode van de os module gebruiken samen met een generator (een generator is een krachtige iterator die zijn status behoudt, weet je nog? ). De volgende code werkt prima met beide versies: Python 2 en Python 3.

Hier is een code:

import os
def files(path):  
    for file in os.listdir(path):
        if os.path.isfile(os.path.join(path, file)):
            yield file
for file in files("."):  
    print (file)

De methode listdir() retourneert de lijst met vermeldingen voor de opgegeven map. De methode os.path.isfile() retourneert True als het gegeven item een ​​bestand is. En de operator yield beëindigt de functie, maar behoudt zijn huidige status en retourneert alleen de naam van het item dat als bestand is gedetecteerd. Met al het bovenstaande kunnen we de generatorfunctie doorlopen.


Antwoord 13

Het retourneren van een lijst met absolute bestandspaden, komt niet terug in submappen

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

Antwoord 14

Een wijze leraar vertelde me ooit dat:

Als er verschillende gevestigde manieren zijn om iets te doen, is geen van alle goed voor alle gevallen.

Ik zal dus een oplossing toevoegen voor een subset van het probleem: vaak willen we alleen controleren of een bestand overeenkomt met een start-string en een eind-string, zonder naar subdirectories te gaan. We willen dus graag een functie die een lijst met bestandsnamen retourneert, zoals:

filenames = dir_filter('foo/baz', radical='radical', extension='.txt')

Als u eerst twee functies wilt declareren, kunt u dit doen:

def file_filter(filename, radical='', extension=''):
    "Check if a filename matches a radical and extension"
    if not filename:
        return False
    filename = filename.strip()
    return(filename.startswith(radical) and filename.endswith(extension))
def dir_filter(dirname='', radical='', extension=''):
    "Filter filenames in directory according to radical and extension"
    if not dirname:
        dirname = '.'
    return [filename for filename in os.listdir(dirname)
                if file_filter(filename, radical, extension)]

Deze oplossing kan gemakkelijk worden gegeneraliseerd met reguliere expressies (en misschien wilt u een argument pattern toevoegen, als u niet wilt dat uw patronen altijd aan het begin of einde van de bestandsnaam blijven hangen).


Antwoord 15

import os
import os.path
def get_files(target_dir):
    item_list = os.listdir(target_dir)
    file_list = list()
    for item in item_list:
        item_dir = os.path.join(target_dir,item)
        if os.path.isdir(item_dir):
            file_list += get_files(item_dir)
        else:
            file_list.append(item_dir)
    return file_list

Hier gebruik ik een recursieve structuur.


Antwoord 16

Generatoren gebruiken

import os
def get_files(search_path):
     for (dirpath, _, filenames) in os.walk(search_path):
         for filename in filenames:
             yield os.path.join(dirpath, filename)
list_files = get_files('.')
for filename in list_files:
    print(filename)

Antwoord 17

Een andere zeer leesbare variant voor Python 3.4+ is het gebruik van pathlib.Path.glob:

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

Het is eenvoudig om specifieker te maken, b.v. zoek alleen naar Python-bronbestanden die geen symbolische links zijn, ook in alle submappen:

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

Antwoord 18

Voor Python 2:

pip install rglob

Doe dan

import rglob
file_list = rglob.rglob("/home/base/dir/", "*")
print file_list

Antwoord 19

Hier is mijn algemene functie hiervoor. Het geeft een lijst met bestandspaden terug in plaats van bestandsnamen, omdat ik dat nuttiger vond. Het heeft een paar optionele argumenten die het veelzijdig maken. Ik gebruik het bijvoorbeeld vaak met argumenten zoals pattern='*.txt' of subfolders=True.

import os
import fnmatch
def list_paths(folder='.', pattern='*', case_sensitive=False, subfolders=False):
    """Return a list of the file paths matching the pattern in the specified 
    folder, optionally including files inside subfolders.
    """
    match = fnmatch.fnmatchcase if case_sensitive else fnmatch.fnmatch
    walked = os.walk(folder) if subfolders else [next(os.walk(folder))]
    return [os.path.join(root, f)
            for root, dirnames, filenames in walked
            for f in filenames if match(f, pattern)]

Antwoord 20

Ik zal een voorbeeld van een one-liner geven waarin het bronpad en het bestandstype als invoer kunnen worden opgegeven. De code retourneert een lijst met bestandsnamen met de extensie csv. Gebruik . voor het geval alle bestanden moeten worden teruggestuurd. Hiermee worden ook de submappen recursief gescand.

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

Wijzig indien nodig bestandsextensies en bronpad.


Antwoord 21

dircache is “Verouderd sinds versie 2.6: De dircache-module is verwijderd in Python 3.0.”

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

LEAVE A REPLY

Please enter your comment!
Please enter your name here

Other episodes