ฉันจะแสดงรายการไฟล์ทั้งหมดของไดเร็กทอรีใน Python และเพิ่มลงในไฟล์list?

ตอบ

os.listdir()คุณจะได้รับทุกอย่างที่อยู่ในไดเรกทอรี - ไฟล์และไดเรกทอรี

หากคุณต้องการเพียงแค่ไฟล์ คุณสามารถกรองข้อมูลนี้โดยใช้os.path:

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

หรือคุณสามารถใช้os.walk()ซึ่งจะให้ผลตอบแทนสองรายการสำหรับแต่ละไดเร็กทอรีที่เข้าชม - แบ่งออกเป็นไฟล์และdirsสำหรับคุณ หากคุณต้องการเพียงไดเร็กทอรีระดับบนสุด คุณสามารถทำลายได้ในครั้งแรกที่มันให้ผล

from os import walk

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

หรือสั้นกว่า:

from os import walk

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

ฉันชอบใช้globโมดูลมากกว่า เนื่องจากเป็นการจับคู่รูปแบบและการขยาย

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

มันจับคู่รูปแบบโดยสัญชาตญาณ

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

มันจะส่งคืนรายการพร้อมไฟล์ที่สืบค้น:

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

os.listdir() - list in the current directory

ด้วย listdir ในโมดูล os คุณจะได้รับไฟล์และโฟลเดอร์ใน dir . ปัจจุบัน

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

กำลังดูในไดเร็กทอรี

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

glob from glob

ด้วย glob คุณสามารถระบุประเภทของไฟล์ที่จะแสดงรายการเช่นนี้

import glob

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

glob ในรายการความเข้าใจ

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

รับเส้นทางแบบเต็มของไฟล์เท่านั้นในไดเร็กทอรีปัจจุบัน

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

Getting the full path name with os.path.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']

Walk: going through sub directories

os.walk ส่งคืนรูท รายการไดเร็กทอรี และรายการไฟล์ นั่นคือเหตุผลที่ฉันคลายแพ็กมันใน r, d, f ในลูป for; จากนั้นจะค้นหาไฟล์และไดเร็กทอรีอื่นในโฟลเดอร์ย่อยของรูทและไปเรื่อยๆ จนกว่าจะไม่มีโฟลเดอร์ย่อย

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(): get files in the current directory (Python 2)

ใน Python 2 หากคุณต้องการรายชื่อไฟล์ในไดเร็กทอรีปัจจุบัน คุณต้องระบุอาร์กิวเมนต์เป็น '.' หรือ os.getcwd() ในวิธี os.listdir

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

To go up in the directory tree

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

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

Get files: os.listdir() in a particular directory (Python 2 and 3)

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

Get files of a particular subdirectory with os.listdir()

import os

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

os.walk('.') - current directory

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

next(os.walk('.')) and 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:\\') - get the full path - list comprehension

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

os.walk - get full path - all files in sub dirs**

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() - get only txt files

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

Using glob to get the full path of the files

หากฉันต้องการเส้นทางที่แน่นอนของไฟล์:

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

Using os.path.isfile to avoid directories in the list

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

Using pathlib from 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

ด้วยlist comprehension:

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

หรือใช้pathlib.Path()แทนpathlib.Path(".")

Use glob method 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

Get all and only files with 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']

Get only files with next and walk in a directory

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

Get only directories with next and walk in a directory

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

Get all the subdir names with 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() from Python 3.5 and greater

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

Examples:

Ex. 1: How many files are there in the subdirectories?

ในตัวอย่างนี้ เรามองหาจำนวนไฟล์ที่รวมอยู่ในไดเร็กทอรีและไดเร็กทอรีย่อยทั้งหมด

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'

Ex.2: How to copy all files from a directory to another?

สคริปต์เพื่อสั่งการในคอมพิวเตอร์ของคุณเพื่อค้นหาไฟล์ประเภททั้งหมด (ค่าเริ่มต้น: pptx) และคัดลอกไฟล์เหล่านั้นในโฟลเดอร์ใหม่

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

Ex. 3: How to get all the files in a txt file

ในกรณีที่คุณต้องการสร้างไฟล์ txt ที่มีชื่อไฟล์ทั้งหมด:

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

Example: txt with all the files of an hard drive

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

All the file of C:\ in one text file

นี่เป็นเวอร์ชันที่สั้นกว่าของโค้ดก่อนหน้า เปลี่ยนโฟลเดอร์ที่จะเริ่มค้นหาไฟล์หากคุณต้องการเริ่มจากตำแหน่งอื่น รหัสนี้สร้างไฟล์ข้อความขนาด 50 MB บนคอมพิวเตอร์ของฉันโดยมีบางอย่างน้อยกว่า 500.000 บรรทัดพร้อมไฟล์ที่มีเส้นทางที่สมบูรณ์

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

How to write a file with all paths in a folder of a type

ด้วยฟังก์ชันนี้ คุณสามารถสร้างไฟล์ txt ที่จะมีชื่อประเภทไฟล์ที่คุณค้นหา (เช่น pngfile.txt) พร้อมพาธแบบเต็มของไฟล์ประเภทนั้นทั้งหมด ฉันคิดว่ามันอาจจะมีประโยชน์ในบางครั้ง

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

(New) Find all files and open them with tkinter GUI

ฉันแค่ต้องการเพิ่มแอพเล็ก ๆ ในปี 2019 นี้เพื่อค้นหาไฟล์ทั้งหมดใน dir และสามารถเปิดได้โดยดับเบิลคลิกที่ชื่อไฟล์ในรายการ ใส่คำอธิบายภาพที่นี่

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()
import os
os.listdir("somedirectory")

จะส่งคืนรายการไฟล์และไดเร็กทอรีทั้งหมดใน "somedirectory"

โซลูชันบรรทัดเดียวเพื่อรับเฉพาะรายการไฟล์ (ไม่มีไดเรกทอรีย่อย):

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

หรือชื่อพาธสัมบูรณ์:

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

รับเส้นทางไฟล์แบบเต็มจากไดเร็กทอรีและไดเร็กทอรีย่อยทั้งหมด

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

  • เส้นทางที่ฉันระบุในฟังก์ชันด้านบนมี 3 ไฟล์ โดยสองไฟล์อยู่ในไดเรกทอรีราก และอีกไฟล์หนึ่งในโฟลเดอร์ย่อยชื่อ "SUBFOLDER" ตอนนี้คุณสามารถทำสิ่งต่าง ๆ เช่น:
  • print full_file_paths ซึ่งจะพิมพ์รายการ:

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

หากต้องการ คุณสามารถเปิดและอ่านเนื้อหา หรือเน้นเฉพาะไฟล์ที่มีนามสกุล ".dat" เช่นในโค้ดด้านล่าง:

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

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

ตั้งแต่เวอร์ชัน 3.4 มีตัววนซ้ำในตัวสำหรับสิ่งนี้ซึ่งมีประสิทธิภาพมากกว่าos.listdir():

pathlib: ใหม่ในเวอร์ชัน 3.4.

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

ตามPEP 428จุดมุ่งหมายของpathlibไลบรารีคือการจัดเตรียมลำดับชั้นอย่างง่ายของคลาสเพื่อจัดการเส้นทางของระบบไฟล์และการดำเนินการทั่วไปที่ผู้ใช้ทำ

os.scandir(): ใหม่ในเวอร์ชัน 3.5.

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

โปรดทราบว่าos.walk()ใช้os.scandir()แทนos.listdir()จากรุ่น 3.5 และความเร็วได้เพิ่มขึ้น 2-20 ครั้งตามPEP 471

ฉันยังแนะนำให้อ่านความคิดเห็นของ ShadowRanger ด้านล่าง

หมายเหตุเบื้องต้น

  • แม้ว่าจะมีความแตกต่างที่ชัดเจนระหว่างเงื่อนไขของไฟล์และไดเรกทอรีในข้อความคำถาม บางคนอาจโต้แย้งว่าจริงๆ แล้วไดเรกทอรีเป็นไฟล์พิเศษ
  • คำสั่ง: " ไฟล์ทั้งหมดของไดเร็กทอรี " สามารถตีความได้สองวิธี:
    1. ทายาทสายตรงทั้งหมด(หรือระดับ 1) เท่านั้น
    2. ทายาททั้งหมดในแผนผังไดเร็กทอรีทั้งหมด (รวมถึงรายการในไดเร็กทอรีย่อย)
  • เมื่อถามคำถาม ฉันคิดว่าPython 2เป็นเวอร์ชันLTSอย่างไรก็ตาม ตัวอย่างโค้ดจะถูกเรียกใช้โดยPython 3 ( .5 ) (ฉันจะเก็บไว้ให้สอดคล้องกับPython 2มากที่สุดเท่าที่จะเป็นไปได้ รวมถึงโค้ดใดๆ ที่เป็นของPythonที่ฉันจะโพสต์นั้นมาจากv3.5.4 - เว้นแต่จะระบุไว้เป็นอย่างอื่น) ที่มีผลที่ตามมาที่เกี่ยวข้องกับคำหลักอื่นในคำถาม: " เพิ่มลงในรายการ ":

    • ในเวอร์ชันก่อนหน้าของPython 2.2ลำดับ (iterables) ส่วนใหญ่จะแสดงรายการ (tuples, sets, ...)
    • ในPython 2.2แนวคิดของตัวสร้าง ( [Python.Wiki]: Generators ) - ได้รับความอนุเคราะห์จาก[Python 3]: คำสั่งผลตอบแทน ) - ได้รับการแนะนำ เมื่อเวลาผ่านไป ตัวสร้างคู่กันก็เริ่มปรากฏขึ้นสำหรับฟังก์ชันที่ส่งคืน/ทำงานกับรายการ
    • ในPython 3 ตัวสร้างเป็นพฤติกรรมเริ่มต้น
    • ไม่แน่ใจว่าการส่งคืนรายการยังคงบังคับอยู่หรือไม่ (หรือตัวสร้างก็ทำได้เช่นกัน) แต่การส่งตัวสร้างไปยังตัวสร้างรายการจะสร้างรายการขึ้นมา (และใช้งานด้วย) ตัวอย่างด้านล่างแสดงความแตกต่างใน[Python 3]: map ( function, iterable, ... )
    >>> 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'>)
    
  • ตัวอย่างจะขึ้นอยู่กับไดเร็กทอรีชื่อroot_dir ที่มีโครงสร้างดังต่อไปนี้ (ตัวอย่างนี้มีไว้สำหรับWinแต่ฉันใช้ทรีเดียวกันบนLnxด้วย):

    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
    


โซลูชั่น

วิธีการแบบเป็นโปรแกรม:

  1. [Python 3]: ระบบปฏิบัติการ listdir ( เส้นทาง='.' )

    Return a list containing the names of the entries in the directory given by path. The list is in arbitrary order, and does not include the special entries '.' and '..' ...


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

    ตัวอย่างที่ซับซ้อนยิ่งขึ้น ( 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()
    

    หมายเหตุ :

    • มีการใช้งานสองแบบ:
      • เครื่องที่ใช้เครื่องกำเนิดไฟฟ้า (แน่นอนว่าที่นี่ดูเหมือนไร้ประโยชน์เนื่องจากฉันแปลงผลลัพธ์เป็นรายการทันที)
      • แบบคลาสสิก (ชื่อฟังก์ชันที่ลงท้ายด้วย_old )
    • ใช้การเรียกซ้ำ (เพื่อเข้าสู่ไดเรกทอรีย่อย)
    • สำหรับการใช้งานแต่ละครั้งมีสองหน้าที่:
      • อันที่ขึ้นต้นด้วยขีดล่าง ( _ ): "ส่วนตัว" (ไม่ควรเรียกโดยตรง) - ที่ใช้งานได้ทั้งหมด
      • สาธารณะ (wrapper ก่อนหน้า): เพียงแค่ตัดเส้นทางเริ่มต้น (ถ้าจำเป็น) ออกจากรายการที่ส่งคืน มันเป็นการใช้งานที่น่าเกลียด แต่มันเป็นความคิดเดียวที่ฉันจะได้มาถึงจุดนี้
    • ในแง่ของประสิทธิภาพ โดยทั่วไปแล้วตัวสร้างจะเร็วกว่าเล็กน้อย (พิจารณาทั้งเวลาการสร้างและ การวนซ้ำ ) แต่ฉันไม่ได้ทดสอบพวกมันในฟังก์ชันแบบเรียกซ้ำ และฉันกำลังวนซ้ำภายในฟังก์ชันเหนือตัวสร้างภายใน - ไม่รู้ว่าประสิทธิภาพเป็นอย่างไร เป็นมิตรคือว่า
    • เล่นกับข้อโต้แย้งเพื่อให้ได้ผลลัพธ์ที่แตกต่างกัน


    เอาท์พุต :

    (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]: ระบบปฏิบัติการ scandir ( path='.' ) ( Python 3.5 +, backport: [PyPI]: scandir )

    Return an iterator of os.DirEntry objects corresponding to the entries in the directory given by path. The entries are yielded in arbitrary order, and the special entries '.' and '..' are not included.

    Using scandir() instead of listdir() can significantly increase the performance of code that also needs file type or file attribute information, because os.DirEntry objects expose this information if the operating system provides it when scanning a directory. All os.DirEntry methods may perform a system call, but is_dir() and is_file() usually only require a system call for symbolic links; os.DirEntry.stat() always requires a system call on Unix but only requires one for symbolic links on 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
    

    หมายเหตุ :

    • มันคล้ายกับ os.listdir
    • แต่ยังมีความยืดหยุ่นมากกว่า (และมีฟังก์ชันการทำงานที่มากกว่า) Python ic ที่มากกว่า(และในบางกรณีเร็วกว่า)


  1. [Python 3]: ระบบปฏิบัติการ เดิน ( top, topdown=True, onerror=None, followlinks=False )

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


    >>> 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', [], [])
    

    หมายเหตุ :

    • ภายใต้ฉากนั้นมันใช้os.scandir( os.listdirในเวอร์ชั่นเก่ากว่า)
    • ทำหน้าที่ยกของหนักโดยการเกิดซ้ำในโฟลเดอร์ย่อย


  1. [Python 3]: glob. glob ( ชื่อพาธ, *, เรียกซ้ำ=False ) ( [Python 3]: glob. iglob ( ชื่อพาธ, *, เรียกซ้ำ=False ) )

    Return a possibly-empty list of path names that match pathname, which must be a string containing a path specification. pathname can be either absolute (like /usr/src/Python-1.5/Makefile) or relative (like ../../Tools/*/*.gif), and can contain shell-style wildcards. Broken symlinks are included in the results (as in the shell).
    ...
    Changed in version 3.5: Support for recursive globs using “**”.


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

    หมายเหตุ :

    • การใช้งาน os.listdir
    • สำหรับต้นไม้ใหญ่ (โดยเฉพาะถ้าเปิดแบบเรียกซ้ำ ) iglobจะดีกว่า
    • อนุญาตการกรองขั้นสูงตามชื่อ (เนื่องจากสัญลักษณ์แทน)


  1. [Python 3]: คลาส pathlib เส้นทาง ( *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']
    

    หมายเหตุ :

    • นี่เป็นวิธีหนึ่งในการบรรลุเป้าหมายของเรา
    • มันเป็นรูปแบบOOPของการจัดการเส้นทาง
    • มาพร้อมฟังก์ชันมากมาย


  1. [Python 2]: dircache.listdir (เส้นทาง) ( 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 - ไลบรารีฟังก์ชันต่างประเทศสำหรับ Python ( เฉพาะPOSIX )

    ctypes is a foreign function library for Python. It provides C compatible data types, and allows calling functions in DLLs or shared libraries. It can be used to wrap these libraries in pure Python.

    code_ctypes.py :

    #!/usr/bin/env python3
    
    import sys
    from ctypes import Structure, \
        c_ulonglong, c_longlong, c_ushort, c_ubyte, c_char, c_int, \
        CDLL, POINTER, \
        create_string_buffer, get_errno, set_errno, cast
    
    
    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()
    

    หมายเหตุ :

    • มันโหลดสามฟังก์ชั่นจากlibc (โหลดในกระบวนการปัจจุบัน) และเรียกใช้ (สำหรับรายละเอียดเพิ่มเติม ตรวจสอบ[SO]: ฉันจะตรวจสอบว่าไฟล์มีอยู่โดยไม่มีข้อยกเว้นได้อย่างไร (คำตอบของ CristiFati) - บันทึกล่าสุดจากรายการ#4 ). นั่นจะวางแนวทางนี้ไว้ใกล้กับขอบPython / C มาก
    • LinuxDirent64คือการแสดงctypesของstruct dirent64จาก[man7]: dirent.h(0P) ( ค่าคงที่DT_ ก็เช่นกัน ) จากเครื่องของฉัน: Ubtu 16 x64 ( 4.10.0-40-genericและlibc6-dev:amd64 ) สำหรับรสชาติ/เวอร์ชันอื่น ๆ คำจำกัดความของโครงสร้างอาจแตกต่างกัน และหากเป็นเช่นนั้นนามแฝงctypesควรได้รับการอัปเดต มิฉะนั้นจะทำให้เกิดพฤติกรรมที่ไม่ได้กำหนด
    • ส่งคืนข้อมูลในos.walkรูปแบบ 's ฉันไม่ได้รำคาญที่จะเรียกซ้ำ แต่เริ่มจากรหัสที่มีอยู่นั่นอาจเป็นงานเล็กน้อย
    • ทุกอย่างสามารถทำได้บนWinเช่นกัน ข้อมูล (ไลบรารี ฟังก์ชัน โครงสร้าง ค่าคงที่ ...) ต่างกัน


    เอาท์พุต :

    [[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 ( เฉพาะวิน )

    Retrieves a list of matching filenames, using the Windows Unicode API. An interface to the API FindFirstFileW/FindNextFileW/Find close functions.


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

    หมายเหตุ :


  1. ติดตั้งแพ็คเกจบุคคลที่สาม (อื่น ๆ ) ที่หลอกลวง
    • เป็นไปได้มากว่าจะใช้หนึ่ง (หรือมากกว่า) ข้างต้น (อาจมีการปรับแต่งเล็กน้อย)


หมายเหตุ :

  • รหัสมีไว้เพื่อให้พกพาได้ (ยกเว้นสถานที่ที่กำหนดเป้าหมายเป็นพื้นที่เฉพาะ - ซึ่งถูกทำเครื่องหมาย) หรือข้าม:

    • แพลตฟอร์ม ( Nix , Win , )
    • เวอร์ชันไพทอน (2, 3, )
  • รูปแบบพาธหลายแบบ (แบบสัมบูรณ์, แบบสัมพัทธ์) ถูกใช้ในตัวแปรด้านบน เพื่อแสดงให้เห็นว่า "เครื่องมือ" ที่ใช้นั้นมีความยืดหยุ่นในทิศทางนี้

  • os.listdirและos.scandirใช้opendir / readdir / closedir ( [MS.Docs]: ฟังก์ชัน FindFirstFileW / [MS.Docs]: ฟังก์ชัน FindNextFileW / [MS.Docs]: ฟังก์ชัน FindClose ) (ผ่าน[GitHub]: python/cpython - (master) cpython/ โมดูล/posixmodule.c )

  • win32file.FindFilesWใช้ฟังก์ชั่นเหล่านั้น ( เฉพาะWin ) เช่นกัน (ผ่าน[GitHub]: mhammond/pywin32 - (master) pywin32/win32/src/win32file.i )

  • _get_dir_content (จากจุดที่#1. ) สามารถนำไปใช้ได้โดยใช้วิธีการใดๆ เหล่านี้ (บางวิธีอาจต้องการงานมากกว่าและบางวิธีน้อยกว่า)

    • การกรองขั้นสูงบางอย่าง (แทนที่จะเป็นแค่ file vs. dir) สามารถทำได้ เช่นอาร์กิวเมนต์include_foldersอาจถูกแทนที่ด้วยอาร์กิวเมนต์อื่น (เช่นfilter_func ) ซึ่งจะเป็นฟังก์ชันที่ใช้พาธเป็นอาร์กิวเมนต์: filter_func=lambda x: True(ไม่ได้แยกออก อะไรก็ตาม) และภายใน_get_dir_contentเช่น: if not filter_func(entry_with_path): continue(หากฟังก์ชันล้มเหลวสำหรับหนึ่งรายการ จะถูกข้ามไป) แต่ยิ่งโค้ดมีความซับซ้อนมากขึ้นเท่าใด การดำเนินการก็จะยิ่งใช้เวลานานขึ้นเท่านั้น
  • โนตาเบเน่!เนื่องจากมีการใช้การเรียกซ้ำฉันต้องพูดถึงว่าฉันได้ทำการทดสอบบนแล็ปท็อปของฉัน ( Win 10 x64 ) ไม่เกี่ยวข้องกับปัญหานี้โดยสิ้นเชิงและเมื่อระดับการเรียกซ้ำถึงค่าบางแห่งในช่วง(990 .. 1000) ( recursionlimit - 1,000 (ค่าเริ่มต้น)) ฉันได้รับStackOverflow :) หากแผนผังไดเร็กทอรีเกินขีดจำกัดนั้น (ฉันไม่ใช่ผู้เชี่ยวชาญFSดังนั้นฉันจึงไม่ทราบว่าเป็นไปได้หรือไม่) นั่นอาจเป็นปัญหาได้
    ฉันต้องพูดถึงด้วยว่าฉันไม่ได้พยายามเพิ่มขีด จำกัด การเรียกซ้ำเพราะฉันไม่มีประสบการณ์ในพื้นที่ (ฉันจะเพิ่มได้มากแค่ไหนก่อนที่จะต้องเพิ่ม stack ที่OS ด้วยระดับ) แต่ในทางทฤษฎีแล้ว จะมีโอกาสเกิดความล้มเหลวได้เสมอ หากความลึกของ dir มากกว่าขีดจำกัดการเรียกซ้ำสูงสุดที่เป็นไปได้(บนเครื่องนั้น)

  • ตัวอย่างโค้ดมีไว้เพื่อการสาธิตเท่านั้น นั่นหมายความว่าฉันไม่ได้คำนึงถึงการจัดการข้อผิดพลาด (ฉันไม่คิดว่ามีการลอง / ยกเว้น / อื่น / ในที่สุดก็บล็อก) ดังนั้นรหัสจึงไม่มีประสิทธิภาพ (เหตุผลคือ: เพื่อให้ง่ายและสั้นที่สุด ). สำหรับการผลิตควรเพิ่มการจัดการข้อผิดพลาดด้วย

แนวทางอื่นๆ:

  1. ใช้Pythonเป็นเสื้อคลุมเท่านั้น

    • ทุกอย่างเสร็จสิ้นโดยใช้เทคโนโลยีอื่น
    • เทคโนโลยีนั้นถูกเรียกใช้จากPython
    • รสชาติที่มีชื่อเสียงที่สุดที่ฉันรู้จักคือสิ่งที่ฉันเรียกว่าแนวทางผู้ดูแลระบบ :

      • ใช้Python (หรือภาษาการเขียนโปรแกรมใดๆ สำหรับเรื่องนั้น) เพื่อดำเนินการคำสั่งเชลล์ (และแยกวิเคราะห์ผลลัพธ์)
      • บางคนคิดว่านี่เป็นการแฮ็กที่ดี
      • ฉันคิดว่ามันมากขึ้นเช่นการแก้ปัญหาง่อย ( gainarie ) เช่นการดำเนินการต่อ se จะดำเนินการจากเปลือก ( cmdในกรณีนี้) และดังนั้นจึงไม่ได้มีอะไรจะทำอย่างไรกับงูหลาม
      • การกรอง ( grep/ findstr) หรือการจัดรูปแบบเอาต์พุตสามารถทำได้ทั้งสองด้าน แต่ฉันจะไม่ยืนยัน นอกจากนี้ ฉันจงใจใช้os.systemแทน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
      

    โดยทั่วไปควรหลีกเลี่ยงวิธีการนี้ เนื่องจากหากรูปแบบเอาต์พุตของคำสั่งบางรูปแบบแตกต่างกันเล็กน้อยระหว่างเวอร์ชัน/รสชาติของระบบปฏิบัติการโค้ดการแยกวิเคราะห์ควรได้รับการดัดแปลงด้วยเช่นกัน ไม่ต้องพูดถึงความแตกต่างระหว่างสถานที่)

ฉันชอบคำตอบของ adamkมาก โดยแนะนำให้คุณใช้glob()จากโมดูลที่มีชื่อเดียวกัน สิ่งนี้ช่วยให้คุณมีรูปแบบที่ตรงกับ*s

แต่อย่างที่คนอื่น ๆ ระบุไว้ในความคิดเห็นglob()อาจสะดุดกับทิศทางทับที่ไม่สอดคล้องกัน เพื่อช่วยในเรื่องนั้น เราขอแนะนำให้คุณใช้join()and expanduser()ฟังก์ชั่นในos.pathโมดูล และอาจรวมถึงgetcwd()ฟังก์ชันในosโมดูลด้วย

เป็นตัวอย่าง:

from glob import glob

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

ด้านบนนี้แย่มาก - เส้นทางได้รับการฮาร์ดโค้ดแล้ว และจะใช้งานได้เฉพาะบน Windows ระหว่างชื่อไดรฟ์กับชื่อที่\ถูกฮาร์ดโค้ดเข้าไปในพาธ

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

ด้านบนใช้งานได้ดีกว่า แต่ใช้ชื่อโฟลเดอร์Usersที่มักพบใน Windows และไม่ค่อยพบในระบบปฏิบัติการอื่น นอกจากนี้ยังขึ้นอยู่กับผู้ใช้ที่มีชื่อเฉพาะ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'))

ซึ่งทำงานได้อย่างสมบูรณ์แบบในทุกแพลตฟอร์ม

อีกตัวอย่างที่ยอดเยี่ยมที่ทำงานข้ามแพลตฟอร์มได้อย่างสมบูรณ์แบบและทำสิ่งที่แตกต่างออกไปเล็กน้อย:

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

หวังว่าตัวอย่างเหล่านี้จะช่วยให้คุณเห็นพลังของฟังก์ชันบางอย่างที่คุณสามารถหาได้ในโมดูลไลบรารี Python มาตรฐาน

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 

หากคุณกำลังมองหาการใช้งาน Python ของfindนี่เป็นสูตรที่ฉันใช้ค่อนข้างบ่อย:

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

ดังนั้นผมจึงทำ PyPI แพคเกจออกมาจากมันและยังมีพื้นที่เก็บข้อมูล GitHub ฉันหวังว่าบางคนจะพบว่ามีประโยชน์สำหรับรหัสนี้

เพื่อผลลัพธ์ที่ดียิ่งขึ้น คุณสามารถใช้listdir()เมธอดของosโมดูลร่วมกับตัวสร้าง โค้ดต่อไปนี้ใช้ได้ดีกับทั้งสองเวอร์ชัน: Python 2 และ Python 3

นี่คือรหัส:

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()วิธีการส่งกลับรายการของรายการสำหรับไดเรกทอรีที่กำหนด เมธอดos.path.isfile()ส่งคืนTrueหากรายการที่กำหนดเป็นไฟล์ และตัวyieldดำเนินการออกจาก func แต่คงสถานะปัจจุบันไว้ และจะส่งกลับเฉพาะชื่อของรายการที่ตรวจพบว่าเป็นไฟล์ ทั้งหมดข้างต้นช่วยให้เราวนรอบฟังก์ชันตัวสร้าง

การส่งคืนรายการพาธไฟล์สัมบูรณ์ ไม่เรียกซ้ำในไดเร็กทอรีย่อย

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

อาจารย์ผู้มีปัญญาท่านหนึ่งเคยเล่าให้ฟังว่า

When there are several established ways to do something, none of them is good for all cases.

ฉันจะเพิ่มวิธีแก้ปัญหาสำหรับชุดย่อยของปัญหา: บ่อยครั้ง เราต้องการตรวจสอบว่าไฟล์ตรงกับสตริงเริ่มต้นและสตริงสิ้นสุดหรือไม่ โดยไม่ต้องไปที่ไดเรกทอรีย่อย เราต้องการฟังก์ชันที่ส่งคืนรายการชื่อไฟล์ เช่น:

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

หากคุณสนใจที่จะประกาศสองฟังก์ชันก่อน สามารถทำได้:

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

โซลูชันนี้สามารถสรุปได้ง่ายด้วยนิพจน์ทั่วไป (และคุณอาจต้องการเพิ่มpatternอาร์กิวเมนต์ ถ้าคุณไม่ต้องการให้รูปแบบของคุณติดอยู่ที่จุดเริ่มต้นหรือจุดสิ้นสุดของชื่อไฟล์เสมอ)

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

ที่นี่ฉันใช้โครงสร้างแบบเรียกซ้ำ

การใช้เครื่องกำเนิดไฟฟ้า

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)

ตัวแปรอื่นที่อ่านได้มากสำหรับ Python 3.4+ กำลังใช้ pathlib.Path.glob:

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

การทำให้เฉพาะเจาะจงมากขึ้นเป็นเรื่องง่าย เช่น ค้นหาเฉพาะไฟล์ต้นฉบับของ Python ที่ไม่ใช่ลิงก์สัญลักษณ์ รวมไปถึงในไดเรกทอรีย่อยทั้งหมดด้วย:

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

สำหรับหลาม 2:

pip install rglob

แล้วทำ

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

นี่คือฟังก์ชันเอนกประสงค์ของฉันสำหรับสิ่งนี้ มันส่งคืนรายการพา ธ ของไฟล์มากกว่าชื่อไฟล์เนื่องจากฉันพบว่ามีประโยชน์มากกว่า มีอาร์กิวเมนต์ที่ไม่บังคับสองสามข้อที่ทำให้ใช้งานได้หลากหลาย ยกตัวอย่างเช่นฉันมักจะใช้กับการขัดแย้งเหมือนหรือpattern='*.txt'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)]

ฉันจะจัดเตรียมตัวอย่างหนึ่งซับที่สามารถระบุพาธต้นทางและประเภทไฟล์เป็นอินพุตได้ รหัสส่งคืนรายชื่อไฟล์ที่มีนามสกุล csv ใช้. ในกรณีที่ต้องส่งคืนไฟล์ทั้งหมด สิ่งนี้จะสแกนไดเรกทอรีย่อยซ้ำ ๆ ด้วย

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

แก้ไขนามสกุลไฟล์และพาธต้นทางตามต้องการ

dircacheคือ "เลิกใช้แล้วตั้งแต่เวอร์ชัน 2.6: โมดูล dircache ถูกลบใน 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