Bir dizindeki tüm dosyaları nasıl listeleyebilirim?


Yanıtlar:


4213

os.listdir()bir dizinde olan her şeyi alırsınız - dosyalar ve dizinler .

Yalnızca dosya istiyorsanız , bunu kullanarak filtreleyebilirsiniz os.path:

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

veya ziyaret ettiğiniz her dizin için iki listeos.walk() oluşturacak şekilde kullanabilirsiniz - sizin için dosyalara ve dizinlere bölünür . Eğer sadece üst dizini istiyorsanız, ilk veriminde kırabilirsiniz.

from os import walk

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

87
Biraz daha basit: (_, _, filenames) = walk(mypath).next() (yürüyüşün olması gereken en az bir değer
döndüreceğinden eminseniz

9
Tam yolları saklamak için hafif değişiklik: os.walk (mypath) içindeki (dirpath, dirnames, dosya adları) için: checksum_files.extend (os.path.join (dirpath, dosya adı) dosya adlarında dosya adı için) break
okigan

150
f.extend(filenames)aslında eşdeğer değildir f = f + filenames. yerinde extenddeğiştirilirken fekleme işlemi yeni bir bellek konumunda yeni bir liste oluşturur. Bu extend, genellikle daha verimli olduğu anlamına gelir +, ancak birden fazla nesne listeye referans tutarsa ​​bazen karışıklığa neden olabilir. Son olarak, buna f += filenameseşdeğer olduğunu belirtmek gerekir f.extend(filenames), değil f = f + filenames .
Benjamin Hodgson

30
Misterbee, çözümünüz en iyisi, sadece küçük bir gelişme:_, _, filenames = next(walk(mypath), (None, None, []))
bgusach

35
3.x kullanımında(_, _, filenames) = next(os.walk(mypath))
ET-CS

1682

globDesen eşleme ve genişletme yaptığı için modülü kullanmayı tercih ederim .

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

Sorgulanan dosyaları içeren bir liste döndürür:

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

17
listdir + fnmatch için kısayol bu docs.python.org/library/fnmatch.html#fnmatch.fnmatch
Stefano

31
netleştirmek için, bu yok değil "tam yolu" return; her ne olursa olsun, globun genişlemesini döndürür. Örneğin, verilen /home/user/foo/bar/hello.txt, daha sonra dizinde çalışan eğer foo, glob("bar/*.txt")dönecektir bar/hello.txt. Aslında tam (yani, mutlak) yolu istediğiniz durumlar vardır; bu durumlar için bkz. stackoverflow.com/questions/51520/…
michael

1
İlgili: glob ile özyinelemeli dosyaları bulun: stackoverflow.com/a/2186565/4561887
Gabriel Staples

6
bu soruya cevap vermiyor. glob.glob("*")olacaktır.
Jean-François Fabre

güzel!!!! Bu yüzden .... x=glob.glob("../train/*.png")klasörün adını bildiğim sürece, bana yollarımın bir dizi verecektir. Çok havalı!
Jennifer Crosby

858

Python 2 ve 3 ile dosyaların bir listesini alın


os.listdir()

Geçerli dizindeki tüm dosyaları (ve dizinleri) alma (Python 3)

Aşağıda, Python 3'te yalnızca geçerli dizindeki os ve listdir()işlevini kullanarak dosyaları almak için basit yöntemler bulunmaktadır. yürüyüşü kullanabilir - daha sonra tartışılmalıdır).

 import os
 arr = os.listdir()
 print(arr)

 >>> ['$RECYCLE.BIN', 'work.txt', '3ebooks.txt', 'documents']

glob

Glob'u aynı türden veya ortak bir şeyle dosyayı seçmek daha kolay buldum. Aşağıdaki örneğe bakın:

import glob

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

glob liste kavrayışı ile

import glob

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

glob bir işlevle

İşlev, bağımsız değişkende belirtilen uzantının (.txt, .docx ecc.) Bir listesini döndürür

import glob

def filebrowser(ext=""):
    "Returns files with an extension"
    return [f for f in glob.glob(f"*{ext}")]

x = filebrowser(".txt")
print(x)

>>> ['example.txt', 'fb.txt', 'intro.txt', 'help.txt']

glob önceki kodu genişletme

İşlev artık bağımsız değişken olarak ilettiğiniz dize ile eşleşen bir dosya listesi döndürüyor

import glob

def filesearch(word=""):
    """Returns a list with all files with the word/extension in it"""
    file = []
    for f in glob.glob("*"):
        if word[0] == ".":
            if f.endswith(word):
                file.append(f)
                return file
        elif word in f:
            file.append(f)
            return file
    return file

lookfor = "example", ".py"
for w in lookfor:
    print(f"{w:10} found => {filesearch(w)}")

çıktı

example    found => []
.py        found => ['search.py']

İle tam yol adını alma os.path.abspath

Fark ettiğiniz gibi, yukarıdaki kodda dosyanın tam yoluna sahip değilsiniz. Mutlak yola sahip olmanız gerekiyorsa, aldığınız dosyayı argüman olarak koyarak, os.pathmodülün adlı başka bir işlevini kullanabilirsiniz . Daha sonra kontrol edeceğimiz gibi tam yola sahip olmanın başka yolları da var (mexmex, _getfullpathname ile önerildiği gibi değiştirdim )._getfullpathnameos.listdir()abspath

 import os
 files_path = [os.path.abspath(x) for x in os.listdir()]
 print(files_path)

 >>> ['F:\\documenti\applications.txt', 'F:\\documenti\collections.txt']

Bir dosya türünün tam yol adını tüm alt dizinlere alın. walk

Bunu birçok dizinde bir şeyler bulmak için çok yararlı buluyorum ve adı hatırlamadığım bir dosya bulmama yardımcı oldu:

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(): geçerli dizindeki dosyaları al (Python 2)

Python 2'de, geçerli dizindeki dosyaların listesini istiyorsanız, bağımsız değişkeni '.' veya os.listdir yönteminde os.getcwd () yöntemini kullanabilirsiniz.

 import os
 arr = os.listdir('.')
 print(arr)

 >>> ['$RECYCLE.BIN', 'work.txt', '3ebooks.txt', 'documents']

Dizin ağacında yukarı çıkmak için

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

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

Dosyaları alın: os.listdir()belirli bir dizinde (Python 2 ve 3)

 import os
 arr = os.listdir('F:\\python')
 print(arr)

 >>> ['$RECYCLE.BIN', 'work.txt', '3ebooks.txt', 'documents']

Belirli bir alt dizinin dosyalarını os.listdir()

import os

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

os.walk('.') - geçerli dizin

 import os
 arr = next(os.walk('.'))[2]
 print(arr)

 >>> ['5bs_Turismo1.pdf', '5bs_Turismo1.pptx', 'esperienza.txt']

next(os.walk('.')) ve 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:\\') - tam yolu bul - liste anlama

 [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 - tam yol al - alt dizinlerdeki tüm dosyalar **

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() - sadece txt dosyalarını edinin

 arr_txt = [x for x in os.listdir() if x.endswith(".txt")]
 print(arr_txt)

 >>> ['work.txt', '3ebooks.txt']

globDosyaların tam yolunu almak için kullanma

Dosyaların mutlak yoluna ihtiyacım varsa:

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.isfileListedeki dizinleri önlemek için kullanma

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

pathlibPython 3.4'ten kullanma

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

İle list comprehension:

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

Alternatif olarak, kullanmak pathlib.Path()yerinepathlib.Path(".")

Pathlib.Path () öğesinde glob yöntemini kullanma

import pathlib

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

>>> stack_overflow_list.py
>>> stack_overflow_list_tkinter.py

Oswalk ile tüm dosyaları alın

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

Yalnızca sonrakine sahip dosyaları alın ve bir dizinde yürüyün

 import os
 x = next(os.walk('F://python'))[2]
 print(x)

 >>> ['calculator.bat','calculator.py']

Yalnızca bir sonraki dizine sahip dizinleri alın ve bir dizinde yürüyün

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

 >>> ['python3','others']

Tüm alt dizin adlarını şununla al: 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() Python 3.5 ve üstü

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

Örnekler:

Ör. 1: Alt dizinlerde kaç dosya var?

Bu örnekte, tüm dizinde ve alt dizinlerinde bulunan dosya sayısını ararız.

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'

Örnek 2: Tüm dosyalar bir dizinden diğerine nasıl kopyalanır?

Bilgisayarınızda bir türdeki tüm dosyaları (varsayılan: pptx) bulan ve bunları yeni bir klasöre kopyalayan bir komut dosyası.

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 Contabilità 1\conti.txt
>>> _compiti18\Compito Contabilità 1\modula4.txt
>>> _compiti18\Compito Contabilità 1\moduloa4.txt
>>> ------------------------
>>> ==> Found in: `_compiti18` : 3 files

Ör. 3: Bir txt dosyasındaki tüm dosyalar nasıl elde edilir

Tüm dosya adlarını içeren bir txt dosyası oluşturmak istiyorsanız:

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

Örnek: bir sabit sürücünün tüm dosyalarıyla txt

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

Tek bir metin dosyasındaki tüm C: \ dosyası

Bu, önceki kodun daha kısa bir sürümüdür. Başka bir konumdan başlamanız gerekiyorsa, dosyaları bulmaya başlayacağınız klasörü değiştirin. Bu kod, bilgisayarımdaki metin dosyasında 50.000'den daha az bir şeyle 500.000 satırdan daha az bir şey oluşturuyor.

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

Bir türdeki bir klasöre tüm yolları içeren bir dosya nasıl yazılır

Bu işlevle, aradığınız bir dosya türünün adına sahip bir txt dosyası oluşturabilirsiniz (ör. Pngfile.txt), bu türdeki tüm dosyaların tüm tam yoluyla. Bazen faydalı olabilir diye düşünüyorum.

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

(Yeni) Tüm dosyaları bulun ve tkinter GUI ile açın

Sadece 2019'da bir dizindeki tüm dosyaları aramak ve listedeki dosyanın adına çift tıklayarak onları açabilmek için küçük bir uygulama eklemek istedim. resim açıklamasını buraya girin

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

14
Bu, burada sorulmayan sorulara çok fazla cevap veren bir püre. Ayrıca uyarıların veya önerilen yaklaşımların ne olduğunu açıklamaya değer olabilir. Hangisinin ne zaman kullanılacağını daha iyi bilmediğim sürece, aynı yolu yapmanın 20 yoluna karşı tek yönünü bilmekten daha iyi değilim.
cs95

Tamam, ASAP Cevabıma bir göz atacağım ve yöntemler arasındaki farklar vb. Hakkında daha temiz ve daha yararlı bilgiler
sunmaya

Dosya adının bir alt dize içerip içermediğini kontrol ederek dosyanın uzantısını belirlememelisiniz. Bu birçok sıkıntıya neden olabilir. Dosya adının belirli bir alt dize ile bitip bitmediğini her zaman kontrol etmenizi öneririz.
ni1ight

Tamam, @ n1light Kodu değiştirdim ...
Giovanni G. PY

811
import os
os.listdir("somedirectory")

"somedirectory" içindeki tüm dosya ve dizinlerin bir listesini döndürür.


11
Tam yol ile karşılaştırıldığında dosyaların göreli yol, tarafından döndürülen bu dönerglob.glob
xji

22
@JIXiang: os.listdir()her zaman salt dosya adları döndürür (göreli yollar değil). Geri glob.glob()dönen, girdi düzeninin yol biçimi tarafından yönlendirilir.
mklement0

os.listdir () -> Her zaman sağlanan konumun içindeki dizin ve dosyayı listeler. Dosyaları değil, yalnızca dizini listelemenin bir yolu var mı?
RonyA

160

Yalnızca dosya listesini almak için tek satırlık bir çözüm (alt dizin yok):

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

veya mutlak yol adları:

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

7
Sadece bir astar varsa import os. glob()Benden daha az özlü görünüyor .
ArtOfWarfare

4
glob ile ilgili sorun, 'bir şey. bir şey' adlı bir klasörün glob tarafından döndürülmesidir ('/ home / adam /*.*')
Remi

6
OS X'te, paket adı verilen bir şey var. Genellikle bir dosya (.tar gibi) olarak ele alınması gereken bir dizindir. Bunların dosya veya dizin olarak ele alınmasını ister misiniz? Kullanmak glob()bir dosya gibi davranır. Metodunuz onu bir dizin olarak ele alır.
ArtOfWarfare

132

Dizin ve Tüm Alt Dizinlerinden Tam Dosya Yollarını Alma

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

  • Yukarıdaki işlevde sağladığım yol, ikisi kök dizinde ve diğeri "SUBFOLDER" adlı bir alt klasörde olmak üzere 3 dosya içeriyordu. Artık aşağıdakileri yapabilirsiniz:
  • print full_file_paths Liste yazdırılacak:

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

İsterseniz, içeriği açabilir ve okuyabilir veya yalnızca aşağıdaki kodda olduğu gibi ".dat" uzantılı dosyalara odaklanabilirsiniz:

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

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


Tek cevap bu.
thelearner

78

3.4 sürümünden beri , bunun için çok daha verimli olan yerleşik yineleyiciler vardır os.listdir():

pathlib: 3.4 sürümündeki yenilikler.

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

PEP 428'e göre , pathlibkütüphanenin amacı, dosya sistemi yollarını ve kullanıcıların bunlar üzerinde yaptıkları ortak işlemleri gerçekleştirmek için basit bir sınıf hiyerarşisi sağlamaktır.

os.scandir(): 3.5 sürümündeki yenilikler.

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

Not os.walk()kullandığı os.scandir()yerine os.listdir()sürüm 3.5 den, ve hızı göre 2-20 kat artmıştır var PEP 471 .

Aşağıda ShadowRanger'ın yorumunu da okumanızı tavsiye ederim.


1
Teşekkürler! Ben doğrudan geri dönmeyen tek çözüm olduğunu düşünüyorum a list. Tercih edilirse alternatif p.nameolarak ilk yerine kullanılabilir p.
jeromej

1
Hoşgeldiniz! pathlib.Path()Atık israf etmek istemeyeceğim birçok yararlı metodu olduğu için örnek oluşturmayı tercih ederim . Ayrıca str(p)yol adları için onları arayabilirsiniz .
SzieberthAdam

6
Not: os.scandirÇözüm, os.listdirbir os.path.is_fileçek veya benzerine göre daha verimli olacak list( hatta tembel yinelemeden faydalanmıyorsunuz), çünkü os.scandirsize is_fileyinelediği gibi ücretsiz olarak bilgi veren işletim sistemi tarafından sağlanan API'ler kullanıyor , diske dosya başına gidiş dönüş yok stat(Windows'ta, DirEntrysize statücretsiz eksiksiz bilgi, * NIX sistemlerinde , statötesinde bilgi için ihtiyaç duyduğu vb.), ancak kolaylık için ilk önce önbellekler sağlar ). is_fileis_dirDirEntrystat
ShadowRanger

1
entry.nameYalnızca dosya adını entry.pathalmak veya tam yolunu almak için de kullanabilirsiniz . Artık her yerde os.path.join () yok.
user136036

56

Ön notlar

  • Dosya ve dizin arasında açık bir ayrım olmasına rağmenSoru metninde terimleri , bazıları dizinlerin aslında özel dosyalar olduğunu iddia edebilir
  • İfadesi: " bir dizinin tüm dosyaları iki şekilde yorumlanabilir:
    1. Yalnızca tüm doğrudan (veya düzey 1) torunları
    2. Tüm dizin ağacındaki tüm alt öğeler (alt dizinlerdeki olanlar dahil)
  • Sorusu sorulduğunda, ben hayal Python 2 idi LTS ancak kod örnekleri tarafından idare edilecek versiyonu, Python 3 ( 0,5 ) Ben bunları devam edeceğiz ( Python 2 olabildiğince şikayette; ayrıca, herhangi bir kod ait Göndereceğim Python , aksi belirtilmedikçe v3.5.4'ten ). Bunun, " bunları bir listeye ekle " sorusundaki başka bir anahtar kelimeyle ilişkili sonuçları var :

    • Python 2.2 öncesi versiyonlarda, sekanslar (tekrarlanabilirler) çoğunlukla listeler (tuples, set, ...) ile temsil edildi.
    • In Python 2.2 , kavramı jeneratörü ( [Python.Wiki]: Jeneratörler ) - izniyle [Python 3]: verim ifadesi ) - tanıtıldı. Zaman geçtikçe, listeleri döndüren / listelerle çalışan işlevler için jeneratör meslektaşları görünmeye başladı
    • In Python 3 , jeneratör varsayılan davranıştır
    • Bir listeyi döndürmenin hala zorunlu olup olmadığından emin değilsiniz (veya bir jeneratör de yapar), ancak bir oluşturucuyu liste yapıcısına iletmek, listeden bir liste oluşturur (ve ayrıca tüketir). Aşağıdaki örnek [Python 3] üzerindeki farklılıkları göstermektedir : harita ( işlev, yinelenebilir, ... )
    >>> 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'>)
  • Örnekler aşağıdaki yapıya sahip root_dir adlı bir dizine dayanacaktır (bu örnek Win içindir , ancak Lnx üzerinde de aynı ağacı kullanıyorum ):

    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


Çözümler

Programlı yaklaşımlar:

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

    Dizin yolu tarafından verilen girdilerin adlarını içeren bir liste döndürür. Liste keyfi sıradadır ve özel girişleri içermez '.'ve '..'...


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

    Daha ayrıntılı bir örnek ( 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()

    Notlar :

    • İki uygulama vardır:
      • Jeneratörleri kullanan biri (sonucu hemen bir listeye dönüştürdüğüm için elbette burada işe yaramaz görünüyor)
      • Klasik olan ( _old ile biten işlev adları )
    • Özyineleme kullanılır (alt dizinlere girmek için)
    • Her uygulama için iki işlev vardır:
      • Alt çizgi ( _ ) ile başlayan : "özel" (doğrudan çağrılmamalıdır) - tüm işi yapar
      • Genel olan (bir önceki sarmalayıcı): sadece döndürülen girdilerden başlangıç ​​yolunu (gerekirse) çıkarır. Bu çirkin bir uygulama, ama bu noktada gelebileceğim tek fikir
    • Performans açısından, jeneratörler genellikle biraz daha hızlı (hem dikkate oluşturulmasını ve yinelemeyi kez), ama özyinelemeli fonksiyonlar bunları test etmedi ve ayrıca ben iç jeneratörler üzerinde işlevi içinde iterating değilim - nasıl performans bilmiyorum arkadaşça
    • Farklı sonuçlar almak için argümanlarla oynayın


    Çıktı :

    (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 +, arka bağlantı noktası : [PyPI]: scandir )

    Bir yineleyici döndürür os.DirEntry tarafından verilen dizindeki girdileri karşılık gelen nesneler yolu . Girişler keyfi sırada ve özel girişler olarak verilir '.'ve '..'dahil edilmez.

    Kullanılması scandir () yerine listdir () çünkü önemli ölçüde ayrıca dosya türü veya dosya özniteliği bilgiye ihtiyacı kod performansını artırabilir os.DirEntry bir dizin tararken işletim sistemi bunu sağlıyorsa bu bilgileri açığa nesneleri. Tüm os.DirEntry yöntemleri bir sistem çağrısı gerçekleştirebilir, ancak is_dir () ve is_file () genellikle sembolik bağlantılar için yalnızca bir sistem çağrısı gerektirir; os.DirEntry.stat () her zaman Unix üzerinde bir sistem çağrısı gerektirir, ancak Windows'daki sembolik bağlantılar için yalnızca bir tane gerektirir.


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

    Notlar :

    • Benzer os.listdir
    • Ancak aynı zamanda daha esnektir (ve daha fazla işlevsellik sunar), daha fazla Python ic (ve bazı durumlarda daha hızlı)


  1. [Python 3]: os. walk ( top, topdown = Doğru, onerror = Yok, followlinks = Yanlış )

    Ağacı yukarıdan aşağıya veya aşağıdan yukarıya doğru yürüterek bir dizin ağacında dosya adları oluşturun. Dizin kökü ağacındaki her bir dizin için en (dahil üst kendisi), bir 3-tuple verir ( 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', [], [])

    Notlar :

    • Sahnelerin altında kullanır os.scandir( os.listdireski sürümlerde)
    • Alt klasörlerde yinelenerek ağır kaldırmayı yapar


  1. [Python 3]: glob. glob ( yol adı, *, özyinelemeli = Yanlış ) ( [Python 3]: glob. iglob ( yol adı, *, özyinelemeli = Yanlış ) )

    Bir yol belirtimi içeren bir dize olması gereken, yol adıyla eşleşen ve boş olabilecek yol adlarının listesini döndürün . yol adı mutlak (like /usr/src/Python-1.5/Makefile) veya göreli (like ../../Tools/*/*.gif) olabilir ve kabuk tarzı joker karakterler içerebilir. Kırık semboller sonuçlara dahil edilir (kabukta olduğu gibi).
    ...
    3.5 sürümünde değiştirildi : “ **” kullanarak tekrarlayan glob desteği .


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

    Notlar :

    • Kullanımları os.listdir
    • Büyük ağaçlar için (özellikle özyinelemeli açıksa) iglob tercih edilir
    • Ada göre gelişmiş filtrelemeye izin verir (joker karakter nedeniyle)


  1. [Python 3]: sınıf pathlib. Yol ( * yol bölümleri ) ( 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']

    Notlar :

    • Bu, hedefimize ulaşmanın bir yoludur
    • Bu var cepten taşıma yollarının tarzı
    • Birçok işlevsellik sunar


  1. [Python 2]: dircache.listdir (yol) ( yalnızca 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]: [Python 3] aracılığıyla CLOSEDIR (3) : ctypes - Python için yabancı işlev kütüphanesi ( POSIX'a özgü)

    ctypes , Python için yabancı bir işlev kütüphanesidir. C uyumlu veri türleri sağlar ve DLL'lerde veya paylaşılan kitaplıklarda çağrı işlevlerine izin verir. Bu kütüphaneleri saf Python'a sarmak için kullanılabilir.

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

    Notlar :

    • Üç işlevi libc'den (geçerli işlemde yüklü) yükler ve çağırır (daha fazla ayrıntı için [SO] kontrol edin : Bir dosyanın istisnasız olup olmadığını nasıl kontrol ederim? (@ CristiFati'nin cevabı) - 4. maddeden son notlar . ). Bu yaklaşım Python / C kenarına çok yakın
    • LinuxDirent64 olan ctypes temsil yapı dirent64 den [man7]: dirent.h (0P) (so DT_ benim makineden sabitler): Ubtu 16 x 64 ( 4.10.0-40-jenerik ve libc6-dev: amd64'tür ). Diğer tatlar / versiyonlarda, yapı tanımı değişebilir ve eğer öyleyse, ctypes takma adı güncellenmelidir, aksi takdirde Tanımlanmamış Davranış verecektir
    • Verileri os.walk'biçiminde döndürür . Özyinelemeyi yapmak için uğraşmadım, ancak mevcut koddan başlayarak, bu oldukça önemsiz bir görev olurdu
    • Win üzerinde her şey yapılabilir , veriler (kütüphaneler, fonksiyonlar, yapılar, sabitler ...) farklıdır


    Çıktı :

    [cfati@cfati-ubtu16x64-0:~/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 ( Belirli Win )

    Windows Unicode API'sını kullanarak eşleşen dosya adlarının bir listesini alır. API FindFirstFileW / FindNextFileW / Find yakın işlevlerine bir arabirim.


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

    Notlar :


  1. Hile yapan bazı (diğer) üçüncü taraf paketlerini yükleyin
    • Büyük olasılıkla, yukarıdakilerden birine (veya daha fazlasına) dayanacaktır (belki küçük özelleştirmelerle)


Notlar :

  • Kod, taşınabilir (belirli bir alanı hedef alan - işaretli yerler hariç) veya çapraz olmalıdır:

    • platformu ( Nix , Win ,)
    • Python sürümü (2, 3,)
  • Kullanılan "araçların" bu yönde esnek olduklarını göstermek için yukarıdaki varyantlarda çoklu yol stilleri (mutlak, akrabalar) kullanılmıştır.

  • os.listdirve os.scandirkullanımı opendir / readdir / closedir ( [MS.Docs]: FindFirstFileW fonksiyonu / [MS.Docs]: FindNextFileW fonksiyonu / [MS.Docs]: FindClose fonksiyonu ) yoluyla ( [GitHub]: piton / CPython - (ana) CPython / Modüller / posixmodule.c )

  • win32file.FindFilesWBu (kullanan Kazan hem de özel) Fonksiyonlar (yoluyla [GitHub]: mhammond / pywin32 - (ana) pywin32 / Win32 / src / win32file.i )

  • _get_dir_content ( 1. noktadan itibaren ) bu yaklaşımlardan herhangi biri kullanılarak uygulanabilir (bazıları daha fazla çalışma, bazıları daha az gerektirir)

    • (Yerine sadece dosyanın Bazı gelişmiş filtreleme vs dir) yapılabilir: örneğin include_folders argüman yerinden olabilir başka biri tarafından (örneğin filter_func ) bağımsız değişken olarak bir yol alan bir fonksiyon olacağını: filter_func=lambda x: True(bu kırmaması _get_dir_content içinde : if not filter_func(entry_with_path): continue(işlev bir giriş için başarısız olursa, atlanır), ancak kod ne kadar karmaşık olursa, yürütülmesi o kadar uzun sürer
  • Nota bene! Özyineleme kullanıldığından, dizüstü bilgisayarımda ( Win 10 x64 ), bu sorunla tamamen ilgisiz bazı testler yaptığımı ve özyineleme düzeyi (990 .. 1000) aralığında ( özyineleme - 1000 ) değerlere ulaştığında bahsetmeliyim. (varsayılan)), StackOverflow :) aldım . Dizin ağacı bu sınırı aşarsa (Ben bir FS uzmanı değilim , bu yüzden bu mümkün olup olmadığını bilmiyorum), bu bir sorun olabilir.
    Ayrıca , bölgede hiçbir deneyimim olmadığı için özyinelemeyi artırmaya çalışmadığımı da belirtmeliyim (ayrıca yığını arttırmak için ne kadar artırabilirim? OS'deancak derinlik mümkün olan en yüksek özyineleme sınırından (bu makinede) daha büyükse, teoride her zaman başarısızlık olasılığı olacaktır.

  • Kod örnekleri yalnızca gösterim amaçlıdır. Bu, hata işlemeyi hesaba katmadığım anlamına gelir (herhangi bir deneme / hariç / else / nihayet blok olduğunu düşünmüyorum ), bu nedenle kod sağlam değil (nedeni: mümkün olduğunca basit ve kısa tutmak ). İçin üretim , hata ele alma de eklenmelidir

Diğer yaklaşımlar:

  1. Kullanım Python sadece bir sarıcı olarak

    • Her şey başka bir teknoloji kullanılarak yapılır
    • Bu teknoloji Python'dan çağrıldı
    • Bildiğim en ünlü lezzet, sistem yöneticisi yaklaşımı dediğim şey :

      • Kullanım Python yürütmek için (ya da bu konuda herhangi bir programlama dili) kabuk komutlarını (ve onların çıkışları ayrıştırmak)
      • Bazıları bunu düzgün bir kesmek olarak görüyor
      • Ben daha çok topal bir çözüm ( gainarie ) gibi görüyorum , çünkü per se eylem kabuktan yapılıyor ( bu durumda cmd ) ve bu nedenle Python ile bir ilgisi yok .
      • Filtreleme ( grep/ findstr) veya çıktı biçimlendirmesi her iki tarafta da yapılabilir, ancak bunun için ısrar etmeyeceğim. Ayrıca, bile bile kullanılan os.systemyerine 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

    Genel olarak bu yaklaşımdan kaçınılmalıdır, çünkü bazı komut çıktı formatları işletim sistemi versiyonları / tatlar arasında biraz farklılık gösterirse , ayrıştırma kodu da uyarlanmalıdır; yerliler arasındaki farklardan bahsetmiyorum).


48

Ben gerçekten sevdim adamk cevabını Kullanmak öne sürerek glob()aynı adlı modülünden. Bu, *s ile desen eşleşmesine sahip olmanızı sağlar .

Ancak diğer insanların yorumlarda belirttiği gibi, glob()tutarsız eğik çizgi yönleri üzerinde takılabilir. Bununla ilgili yardım için, sana kullanmak önermek join()ve expanduser()işlevleri os.pathmodülü ve belki getcwd()de işlev osmodülü, hem de.

Örnek olarak:

from glob import glob

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

Yukarıdaki korkunç - yol sabit kodlanmış ve sadece sürücü adı ve \yola sabit kodlanmış olanlar arasında Windows üzerinde çalışacaktır .

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

Yukarıdakiler daha iyi çalışır, ancak UsersWindows'ta sıklıkla bulunan ve diğer işletim sistemlerinde çok sık bulunmayan klasör adına dayanır . Ayrıca belirli bir ada sahip kullanıcıya dayanır 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'))

Bu, tüm platformlarda mükemmel çalışır.

Platformlarda mükemmel çalışan ve biraz farklı bir şey yapan başka bir harika örnek:

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

Bu örneklerin, standart Python kitaplığı modüllerinde bulabileceğiniz birkaç işlevin gücünü görmenize yardımcı olacağını umuyoruz.


4
Ekstra glob eğlencesi: Python 3.5'ten başlayarak, **ayarladığınız sürece çalışır recursive = True. Buradaki dokümanlara bakın: docs.python.org/3.5/library/glob.html#glob.glob
ArtOfWarfare

36
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 

Teşekkürler! İşler! mükemmel!
ambigus9

23

Bul bir Python uygulaması arıyorsanız , bu oldukça sık kullandığım bir reçetedir:

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

Bu yüzden bir PyPI paketi hazırladım ve bir de GitHub deposu var . Umarım birisi bu kod için potansiyel olarak yararlı bulur.


14

Daha büyük sonuçlar için, bir jeneratörle birlikte modülün listdir()yöntemini kullanabilirsiniz os(jeneratör, durumunu koruyan güçlü bir yineleyicidir, hatırlıyor musunuz?). Aşağıdaki kod her iki sürümde de iyi çalışır: Python 2 ve Python 3.

İşte bir kod:

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)

listdir()Yöntem verilen dizinin girişlerin listesini döndürür. Verilen girdi bir os.path.isfile()dosyaysa yöntem geri döner True. Ve yieldişleç işlevden ayrılır ancak geçerli durumunu korur ve yalnızca dosya olarak algılanan girdinin adını döndürür. Yukarıdakilerin hepsi jeneratör fonksiyonu üzerinde döngü yapmamızı sağlar.


11

Mutlak dosyayolları listesinin döndürülmesi, alt dizinlere geri çekilmez

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

2
Not: os.path.abspath(f)biraz daha ucuz bir yedek olacaktır os.path.join(os.getcwd(),f).
ShadowRanger

Eğer ile başlayan eğer hala daha verimli olurdu cwd = os.path.abspath('.')o zaman, kullanılan cwdyerine '.'ve os.getcwd()yedekli sistem çağrılarının önlemek yükleri boyunca.
Martijn Pieters

10
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

Burada özyinelemeli bir yapı kullanıyorum.


Aynı şey şu şekilde de yapılabilir pathlib:filter(Path.is_file, Path().rglob('*'))
Georgy

9

Akıllı bir öğretmen bana bir keresinde şunları söyledi:

Bir şey yapmanın birkaç yerleşik yolu olduğunda, bunların hiçbiri tüm durumlar için iyi değildir.

Böylece sorunun bir alt kümesi için bir çözüm ekleyeceğim : oldukça sık, biz sadece bir dosyanın alt dizine girmeden bir başlangıç ​​dizesi ve bir bitiş dizesi ile eşleşip eşleşmediğini kontrol etmek istiyoruz. Bu nedenle aşağıdaki gibi bir dosya adı listesi döndüren bir işlev isteriz:

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

İlk önce iki işlevi bildirmek isterseniz, bu yapılabilir:

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

Bu çözüm, normal ifadelerle kolayca genelleştirilebilir (ve patterndesenlerinizin her zaman dosya adının başına veya sonuna yapışmasını istemiyorsanız bir argüman eklemek isteyebilirsiniz).


6

Jeneratörleri kullanma

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)

4

Python 3.4+ için çok okunabilir bir başka varyant da pathlib.Path.glob kullanıyor:

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

Daha spesifik hale getirmek kolaydır, örneğin tüm alt dizinlerde de sadece sembolik bağlantı olmayan Python kaynak dosyalarını arayın:

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

3

İşte bunun için genel amaçlı işlevim. Dosya adlarından ziyade dosya yollarının bir listesini döndürür. Çok yönlü yapan birkaç isteğe bağlı argüman vardır. Örneğin, sık sık pattern='*.txt'veya gibi argümanlarla kullanıyorum 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)]

2

Sourcepath ve dosya türünün girdi olarak sağlanabileceği örnek bir astar sağlayacağım. Kod, csv uzantılı bir dosya adı listesi döndürür. Kullanın . tüm dosyaların iade edilmesi durumunda. Bu aynı zamanda alt dizinleri tekrar tekrar tarar.

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

Dosya uzantılarını ve kaynak yolunu gerektiği gibi değiştirin.


1
Kullanacaksanız glob, sadece kullanın glob('**/*.csv', recursive=True). Bunu os.walk()tekrarlamak için birleştirmeye gerek yoktur ( recursiveve **Python 3.5'ten beri desteklenmektedir).
Martijn Pieters

2

Python2 için: pip install rglob

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

2

dircache "2.6 sürümünden beri kullanımdan kaldırıldı: dircache modülü Python 3.0'da kaldırıldı."

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

17
dirchache "2.6 sürümünden beri kullanımdan kaldırıldı: dircache modülü Python 3.0'da kaldırıldı."
Daniel Reis
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.