디렉토리의 모든 파일을 어떻게 나열합니까?


답변:


4208

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

87
조금 더 간단합니다. (_, _, filenames) = walk(mypath).next() (산책이 적어도 하나의 값을 반환 할 것이라고 확신하는 경우, 그 값이 있어야합니다.)
— misterbee

9
전체 경로를 저장하도록 약간 수정 : os.walk (mypath)의 (dirpath, dirnames, filenames) : checksum_files.extend (osfiles의 파일 이름 : checksum_files.extend (os.path.join (dirpath, filename)) break
— okigan

150
f.extend(filenames)실제로와 같지 않습니다 f = f + filenames. extend수정됩니다 f추가하는 새로운 메모리 위치에 새리스트를 생성하는 반면에 장소. 이는 extend일반적으로보다 효율적이지만 +, 여러 객체가 목록에 대한 참조를 보유하는 경우 때때로 혼란을 초래할 수 있습니다. 마지막으로, 그 지적 그것의 가치는 f += filenames동등하다 f.extend(filenames), 하지 f = f + filenames .
— Benjamin Hodgson

30
@misterbee, 귀하의 솔루션은 최고이며 단 하나의 작은 개선점입니다._, _, filenames = next(walk(mypath), (None, None, []))
— bgusach

35
python 3.x에서 사용(_, _, filenames) = next(os.walk(mypath))
— ET-CS 2

1680

glob패턴 일치 및 확장을 수행 하므로 모듈을 사용하는 것이 좋습니다.

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

쿼리 된 파일이있는 목록을 반환합니다.

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


31
명확히하기 위해 "전체 경로"를 반환 하지 않습니다 . 어쨌든 글로브의 확장을 반환합니다. 예를 들어 주어진 /home/user/foo/bar/hello.txt디렉토리 foo에서 실행되는 경우 glob("bar/*.txt")는을 반환 bar/hello.txt합니다. 실제로 전체 (즉, 절대) 경로를 원하는 경우가 있습니다. 이러한 경우 stackoverflow.com/questions/51520/…을
— Michael

1
관련 : 발견 재귀 글로브와 함께 파일 : stackoverflow.com/a/2186565/4561887
— 가브리엘 스테이 플스

6
이 질문에 대답하지 않습니다. glob.glob("*")할 것이다.
— Jean-François Fabre

아름다운!!!! 그래서 .... x=glob.glob("../train/*.png")폴더 이름을 알고있는 한 내 경로 배열을 제공합니다. 너무 멋져요!
— 제니퍼 크로스비

857

Python 2 및 3으로 파일 목록 가져 오기


os.listdir()

현재 디렉토리의 모든 파일 및 디렉토리를 얻는 방법 (Python 3)

다음 은 Python 3에서 os 및 listdir()함수를 사용하여 현재 디렉토리의 파일 만 검색하는 간단한 방법입니다. 추가 탐색에서는 디렉토리의 폴더를 반환하는 방법을 보여 주지만 하위 디렉토리에는 파일이 없습니다. 걷기를 사용할 수 있습니다-나중에 설명).

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

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

glob

같은 유형의 파일이나 공통된 파일을 선택하는 것이 더 쉽다는 것을 알았습니다. 다음 예를보십시오.

import glob

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

glob 목록 이해

import glob

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

glob 기능으로

이 함수는 인수에 주어진 확장자 (.txt, .docx 등)의 목록을 반환합니다.

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 이전 코드 확장

함수는 이제 인수로 전달한 문자열과 일치하는 파일 목록을 반환합니다

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

산출

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

로 전체 경로 이름 얻기 os.path.abspath

알다시피, 위의 코드에는 파일의 전체 경로가 없습니다. 절대 경로가 필요하면 os.path이라는 모듈 의 다른 함수를 사용 _getfullpathname하여 얻은 파일을 os.listdir()인수로 사용할 수 있습니다. 나중에 확인할 것처럼 전체 경로를 갖는 다른 방법이 있습니다 (mexmex에서 제안한대로 _getfullpathname으로 대체했습니다 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

많은 디렉토리에서 물건을 찾는 데 매우 유용하며 이름을 기억하지 못하는 파일을 찾는 데 도움이되었습니다.

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(): 현재 디렉토리에서 파일 가져 오기 (Python 2)

Python 2에서 현재 디렉토리에있는 파일 목록을 원하면 인수를 '.'로 지정해야합니다. 또는 os.listdir 메소드의 os.getcwd ().

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

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

디렉토리 트리에서 위로 이동하려면

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

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

파일 가져 오기 : os.listdir()특정 디렉토리 (Python 2 및 3)

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

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

다음과 같은 특정 하위 디렉토리의 파일을 가져옵니다. os.listdir()

import os

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

os.walk('.') -현재 디렉토리

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

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

next(os.walk('.')) 과 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:\\') -전체 경로를 얻으십시오-목록 이해

 [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 -전체 경로 가져 오기-하위 디렉토리의 모든 파일 **

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() -txt 파일 만 가져옵니다

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

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

사용 glob파일의 전체 경로를 얻는 데

파일의 절대 경로가 필요한 경우 :

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

>>> F:\acquistionline.txt
>>> F:\acquisti_2018.txt
>>> F:\bootstrap_jquery_ecc.txt

os.path.isfile목록에서 디렉토리를 피하기 위해 사용

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에서 사용

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

pathlib.Path ()에서 glob 메소드 사용

import pathlib

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

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

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

다음 파일 만 가져와 디렉토리로 이동

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

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

다음 디렉토리 만 가져 와서 디렉토리로 이동

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

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

모든 하위 디렉토리 이름을 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() 파이썬 3.5 이상

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

예 :

전의. 1 : 서브 디렉토리에 몇 개의 파일이 있습니까?

이 예에서는 모든 디렉토리 및 해당 서브 디렉토리에 포함 된 파일 수를 찾습니다.

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'

예 2 : 디렉토리에서 다른 파일로 모든 파일을 복사하는 방법?

컴퓨터에서 형식을 가진 모든 파일 (기본값 : 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

전의. 3 : txt 파일의 모든 파일을 가져 오는 방법

모든 파일 이름으로 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)

예 : 하드 드라이브의 모든 파일이 포함 된 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")

하나의 텍스트 파일에있는 C : \의 모든 파일

이것은 이전 코드의 짧은 버전입니다. 다른 위치에서 시작해야하는 경우 파일 찾기를 시작할 폴더를 변경하십시오. 이 코드는 컴퓨터의 텍스트 파일에 50MB 미만의 완전한 경로를 가진 파일이있는 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")

유형의 폴더에 모든 경로를 가진 파일을 작성하는 방법

이 기능을 사용하면 찾고자하는 파일 형식 (예 : pngfile.txt)의 이름을 가진 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) 모든 파일을 찾아 tkinter GUI로 열기

나는이 2019 년에 디렉토리에있는 모든 파일을 검색하고 목록에서 파일 이름을 두 번 클릭하여 열 수있는 작은 응용 프로그램을 추가하고 싶었습니다. 여기에 이미지 설명을 입력하십시오

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

13
여기에 묻지 않은 질문에 대한 답변이 너무 많습니다. 주의 사항이나 권장되는 방법이 무엇인지 설명하는 것이 좋습니다. 언제 사용하는 것이 더 적합한 지 알지 않는 한 한 가지 방법과 20 가지 방법으로 같은 일을하는 것이 좋습니다.
— cs95

최대한 빨리 답변을 살펴보고 방법 등의 차이점에 대한보다 유용한 정보를 사용하여보다 정교하게 작성하려고합니다.
— Giovanni G. PY

파일 이름에 하위 문자열이 포함되어 있는지 확인하여 파일 확장자를 결정해서는 안됩니다. 많은 문제가 발생할 수 있습니다. 파일 이름이 특정 하위 문자열로 끝나는 지 항상 확인하는 것이 좋습니다.
— ni1ight

좋아, @ n1light 코드를 변경했습니다 ...
— Giovanni G. PY

811
import os
os.listdir("somedirectory")

"somedirectory"의 모든 파일 및 디렉토리 목록을 반환합니다.


11
이것은 다음과 같이 반환 된 전체 경로와 비교하여 파일의 상대 경로를 반환합니다.glob.glob
— xji

22
@JIXiang : os.listdir()항상 상대 경로 가 아닌 단순한 파일 이름을 반환합니다 . 무엇 glob.glob()반환 입력 패턴의 경로 형식에 의해 구동된다.
— mklement0

os.listdir ()-> 항상 제공된 위치에있는 디렉토리와 파일을 나열합니다. 파일이 아닌 디렉토리 만 나열하는 방법이 있습니까?
— RonyA

160

파일 목록 만 가져 오는 한 줄 솔루션 (하위 디렉토리 없음) :

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

또는 절대 경로 이름 :

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

7
이미 하나의 라이너 만 있습니다 import os. glob()나 보다 간결한 것 같습니다 .
— ArtOfWarfare

4
glob의 문제점은 'something.something'이라는 폴더가 glob ( '/ home / adam /*.*')에 의해 반환 될 것입니다
— Remi

6
OS X에는 번들이라는 것이 있습니다. 일반적으로 파일 (.tar 등)로 취급해야하는 디렉토리입니다. 그것들을 파일이나 디렉토리로 취급 하시겠습니까? 를 사용 glob()하면 파일로 취급됩니다. 귀하의 방법은 디렉토리로 취급합니다.
— ArtOfWarfare

132

디렉토리 및 모든 서브 디렉토리에서 전체 파일 경로 가져 오기

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 개의 파일이 포함되어 있습니다. 그 중 2 개는 루트 디렉토리에 있고 다른 하나는 "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


이것은 유일한 대답입니다.
— thelearner

78

버전 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
감사! 직접 반환하지 않는 유일한 솔루션이라고 생각합니다 list. 원하는 경우 p.name첫 번째 p대안 대신 사용할 수 있습니다 .
— jeromej

1
어서 오십시오! pathlib.Path()폐기물을 낭비하고 싶지 않은 유용한 방법이 많기 때문에 인스턴스 생성을 선호합니다 . str(p)경로 이름을 요청할 수도 있습니다.
— SzieberthAdam

6
참고 :이 os.scandir솔루션은 필요에 따라 (예 : 반복 반복의 이점을 얻지 못 하더라도) 검사 보다 효율적 os.listdir입니다. 반복시 정보를 무료로 제공하는 OS 제공 API를 사용 하기 때문에 , 디스크마다 디스크로의 왕복 여행이 전혀 없습니다 (Windows의 경우 무료로 완전한 정보를 얻 습니다. * NIX 시스템 에서는 , 등 이외의 정보는 필요 하지만 편의를 위해 먼저 캐시 합니다). os.path.is_filelistos.scandiris_filestatDirEntrystatstatis_fileis_dirDirEntrystat
— ShadowRanger

1
entry.name파일 이름 만 entry.path가져 오거나 전체 경로를 얻는 데 사용할 수도 있습니다 . 더 이상 os.path.join ()이 없습니다.
— user136036

56

예비 메모

  • 파일 과 디렉토리 사이에는 분명한 차이가 있지만질문 텍스트에서 용어 일부는 디렉토리가 실제로 특수 파일이라고 주장 할 수 있습니다
  • 성명서 : " 디렉토리의 모든 파일 두 가지 방식으로 해석 될 수 있습니다.
    1. 모든 직계 자손 만
    2. 전체 디렉토리 트리의 모든 하위 항목 (하위 디렉토리의 하위 항목 포함)
  • 문제는 질문을 받았다 때, 나는 상상 파이썬 2 의했다 LTS의 그러나 코드 샘플에 의해 실행됩니다 버전, 파이썬 3 ( 0.5 ) 내가 그들을하겠습니다 ( 파이썬이 가능한 준수, 또한, 어떤 코드에 속하는 게시 할 Python 은 v3.5.4 에서 가져 왔습니다 -달리 지정하지 않는 한). 그 결과 질문에있는 다른 키워드와 관련된 결과 가 나타 납니다. " 목록에 키워드 추가 ":

    • 파이썬 2.2 이전 버전에서, 시퀀스 (iterables)는 대부분리스트 (튜플, 세트 등)로 표현되었습니다.
    • 에서는 파이썬 2.2 의 개념 발생기 ( [Python.Wiki] 발생기 ) - 호의 [파이썬 3] : yield 문 ) - 도입되었다. 시간이 지남에 따라 목록으로 반환 / 작업 된 함수에 생성기 대응 항목이 나타나기 시작했습니다.
    • 에서 파이썬 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. [파이썬 3] : os. listdir ( path = '.' )

    경로로 주어진 디렉토리에있는 항목의 이름이 포함 된 목록을 반환하십시오. 목록은 임의의 순서이며, 특별 항목을 포함하지 않습니다 '.'및 '..'...


    >>> 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로 끝나는 함수 이름 )
    • 재귀가 사용됩니다 (하위 디렉토리로 들어가기 위해).
    • 각 구현에는 두 가지 기능이 있습니다.
      • 밑줄 ( _ )로 시작하는 것 : "private"(직접 호출해서는 안 됨)-모든 작업을 수행합니다.
      • 공개 경로 (이전의 래퍼) : 반환 된 항목에서 초기 경로 (필요한 경우)를 제거합니다. 그것은 추악한 구현이지만,이 시점에서 내가 올 수있는 유일한 아이디어입니다.
    • 성능 측면에서 생성기는 일반적으로 생성 속도 와 반복 시간을 모두 고려하여 조금 더 빠르지 만 재귀 함수에서 테스트하지 않았으며 내부 생성기보다 함수 내부에서 반복하고 있습니다. 성능을 모릅니다. 친근하다
    • 다른 결과를 얻기 위해 논증을 가지고 노는


    출력 :

    (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. [파이썬 3] : os. scandir ( path = '.' ) ( Python 3.5 +, 백 포트 : [PyPI] : scandir )

    path로 지정된 디렉토리의 엔트리에 대응하는 os.DirEntry 객체 의 반복자를 돌려줍니다 . 항목은 임의의 순서로 산출하고, 특별 항목입니다 및 포함되지 않습니다.'.''..'

    os.DirEntry 객체는 디렉토리를 스캔 할 때 운영 체제에서 정보를 제공하면 os.DirEntry 객체가이 정보를 노출 하므로 listdir () 대신 scandir ()을 사용하면 파일 유형 또는 파일 속성 정보가 필요한 코드의 성능이 크게 향상 될 수 있습니다 . 모든 os.DirEntry 메소드는 시스템 호출을 수행 할 수 있지만 is_dir () 및 is_file ()은 일반적으로 기호 링크에 대한 시스템 호출 만 필요합니다. os.DirEntry.stat ()는 항상 Unix에서 시스템 호출이 필요하지만 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. [파이썬 3] : os. 도보 ( top, topdown = True, onerror = None, followlinks = False )

    트리를 하향식 또는 상향식으로 이동하여 디렉토리 트리에서 파일 이름을 생성하십시오. 디렉토리를 루트로하는 트리의 각 디렉토리를 들어 상단 (를 포함하여 상위 자체)는 3 튜플을 산출한다 ( 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. [파이썬 3] : glob. glob ( pathname, *, recursive = False ) ( [Python 3] : glob. iglob ( pathname, *, recursive = False ) )

    pathname 과 일치하는 비어있는 경로 이름 목록을 리턴합니다. 경로 이름 은 경로 스펙을 포함하는 문자열이어야합니다. 경로 이름 은 절대적 ( /usr/src/Python-1.5/Makefile) 또는 상대적 ( ../../Tools/*/*.gif) 일 수 있으며 쉘 스타일 와일드 카드를 포함 할 수 있습니다. 깨진 심볼릭 링크가 결과에 포함됩니다 (쉘에서와 같이).
    ...
    버전 3.5으로 변경 :“ **”를 사용한 재귀 글로브 지원 .


    >>> 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
    • 큰 나무의 경우 (특히 재귀 가 켜져있는 경우) 이글 롭 이 선호됩니다.
    • 와일드 카드로 인해 이름을 기준으로 고급 필터링 허용


  1. [파이썬 3] : class pathlib. 경로 ( * pathsegments ) ( Python 3.4 +, 백 포트 : [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. [파이썬 2] : dircache.listdir (path) ( 파이썬 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]을 통한 CLOSEDIR (3) : ctypes-Python 용 외부 함수 라이브러리 ( POSIX 특정)

    ctypes 는 파이썬을위한 외부 함수 라이브러리입니다. C 호환 데이터 형식을 제공하며 DLL 또는 공유 라이브러리에서 함수를 호출 할 수 있습니다. 이 라이브러리를 순수한 파이썬으로 감싸는 데 사용할 수 있습니다.

    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 는 [man7] 에서 struct dirent64 의 ctypes 표현 입니다. 내 컴퓨터의 dirent.h (0P) ( DT_ 상수도 마찬가지 임) : Ubtu 16 x64 ( 4.10.0-40-generic 및 libc6-dev : amd64 ). 다른 특징 / 버전에서는 struct 정의가 다를 수 있으며, 그렇다면 ctypes 별칭이 업데이트되어야합니다. 그렇지 않으면 정의되지 않은 동작 이 생성됩니다.
    • os.walk의 형식으로 데이터를 반환 합니다. 나는 그것을 재귀 적으로 만들지 않았지만 기존 코드에서 시작하여 상당히 사소한 작업 일 것입니다.
    • Win 에서도 모든 것이 가능 하며 데이터 (라이브러리, 함수, 구조체, 상수 등)는 다릅니다.


    출력 :

    [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 ( Win 특정)

    Windows Unicode API를 사용하여 일치하는 파일 이름 목록을 검색합니다. API FindFirstFileW / FindNextFileW / Find 닫기 함수에 대한 인터페이스입니다.


    >>> 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의] 파이썬 / CPython의 - (마스터)의 CPython / Modules / posixmodule.c )

  • win32file.FindFilesW( Win 특정) 기능도 사용합니다 ( [GitHub] : mhammond / pywin32-(master) pywin32 / win32 / src / win32file.i )

  • _get_dir_content (포인트 # 1에서 )는 이러한 접근 방식 중 하나를 사용하여 구현할 수 있습니다 (일부는 더 많은 작업이 필요하고 더 적은 작업이 필요함)

    • (대신 파일의 일부 고급 필터링 대 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 -1000 )의 어딘가에 도달했을 때 언급해야합니다 . (기본값)), StackOverflow가 있습니다 :). 디렉토리 트리가 해당 한계를 초과하면 ( FS 전문가가 아니므로 가능한지 모르겠습니다) 문제가 될 수 있습니다.
    또한 지역에 경험이 없기 때문에 재귀 제한 을 늘리지 않았다고 언급해야합니다 ( OS 에서 스택을 늘리기 전에 얼마나 많이 늘릴 수 있습니까?그러나 이론적으로 dir 깊이가 가능한 최대 재귀 한계 (해당 머신에서) 보다 큰 경우 항상 실패 가능성이 있습니다.

  • 코드 샘플은 설명을위한 것입니다. 즉, 오류 처리를 고려하지 않았다는 것을 의미합니다 ( 시도 / 제외 / else / finally 블록 이 없다고 생각 합니다). 코드가 강력하지 않습니다 (이유는 가능한 한 간단하고 짧게 유지해야합니다) ). 들어 생산 , 오류 처리는 물론 추가해야

다른 접근법 :

  1. 랩퍼로만 Python을 사용하십시오.

    • 다른 기술을 사용하여 모든 것이 이루어집니다.
    • 그 기술은 파이썬 에서 불러옵니다
    • 내가 아는 가장 유명한 특징은 시스템 관리자 접근 방식입니다.

      • 쉘 명령 을 실행 하고 출력을 구문 분석 하려면 Python (또는 그 문제에 대한 프로그래밍 언어)을 사용하십시오
      • 일부는 이것을 깔끔한 핵으로 간주합니다
      • 나는 액션 자체가 쉘 ( 이 경우 cmd) 에서 수행 되므로 Python 과 관련이 없으므로 절름발이 해결 방법 ( gainarie ) 과 같이 생각 합니다.
      • 필터링 ( 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

    일반적으로이 접근 방식은 피해야합니다. 일부 명령 출력 형식이 OS 버전 / 맛에 따라 약간 다르면 구문 분석 코드도 조정해야합니다. 로케일 간의 차이점은 말할 것도 없습니다.


48

나는 같은 이름의 모듈 에서을 사용할 것을 제안하는 adamk의 답변을 정말로 좋아했습니다 glob(). 이를 통해 *s 와 패턴을 일치시킬 수 있습니다 .

그러나 다른 사람들이 의견에서 지적했듯이 glob()일관되지 않은 슬래시 방향으로 넘어 질 수 있습니다. 그 도움에, 나는 당신이 사용하는 것이 좋습니다 join()및 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에서 자주 발견되는 다른 OS에서는 그렇지 않습니다. 또한 특정 이름을 가진 사용자에게 의존합니다 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'))

이 예제들이 표준 파이썬 라이브러리 모듈에서 찾을 수있는 몇 가지 함수의 힘을 볼 수 있기를 바랍니다.


4
추가 글로브 재미 : Python 3.5부터는 **설정 한 한 작동합니다 recursive = True. docs.python.org/3.5/library/glob.html#glob.glob
— ArtOfWarfare

35
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 

23

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의 저장소가 . 누군가 가이 코드에 유용 할 수 있기를 바랍니다.


14

더 큰 결과를 얻으려면 생성기와 함께 모듈의 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연산자는 기능을 종료하지만 현재 상태를 유지하며 파일로 탐지 된 항목의 이름 만 반환합니다. 위의 모든 사항을 통해 생성기 기능을 반복 할 수 있습니다.


11

절대 파일 경로 목록을 리턴하면 하위 디렉토리로 재귀하지 않습니다.

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

2
참고 : os.path.abspath(f)대신에 좀 더 저렴합니다 os.path.join(os.getcwd(),f).
— ShadowRanger

당신이 시작하면 나는 아직도 더 효율적인 것 cwd = os.path.abspath('.')후, 사용하는 cwd대신 '.'및 os.getcwd()이중화 시스템 호출을 피할로드에 걸쳐.
— 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

여기서는 재귀 구조를 사용합니다.


한 줄로 다음과 같은 작업을 수행 할 수 있습니다 pathlib.filter(Path.is_file, Path().rglob('*'))
— Georgy

9

현명한 선생님이 한 번 말해 주셨습니다.

어떤 일을하는 몇 가지 확실한 방법이있을 때, 그 중 어느 것도 모든 경우에 좋은 것은 아닙니다.

따라서 문제 의 하위 집합 에 대한 해결책을 추가 할 것입니다. 하위 디렉토리로 이동하지 않고 파일이 시작 문자열과 끝 문자열과 일치하는지 여부 만 확인하려고합니다. 따라서 다음과 같이 파일 이름 목록을 반환하는 함수를 원합니다.

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패턴이 항상 파일 이름의 시작이나 끝을 고수하지 않으려면 인수 를 추가 할 수 있습니다 ).


6

발전기 사용

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+의 또 다른 읽기 쉬운 변형은 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()]

3

여기 내 범용 기능이 있습니다. 더 유용하다는 것을 알았으므로 파일 이름 대신 파일 경로 목록을 반환합니다. 다목적 성을 제공하는 몇 가지 선택적 인수가 있습니다. 예를 들어, 나는 종종 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)]

2

소스 경로와 파일 형식을 입력으로 제공 할 수있는 샘플 하나의 라이너를 제공합니다. 이 코드는 csv 확장자를 가진 파일 이름 목록을 반환합니다. 사용하십시오 . 모든 파일을 반환해야하는 경우 또한 서브 디렉토리를 재귀 적으로 스캔합니다.

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

필요에 따라 파일 확장자와 소스 경로를 수정하십시오.


1
당신이 사용하려고한다면 glob, 그냥 사용하십시오 glob('**/*.csv', recursive=True). 필요가 이것을 결합 없습니다 os.walk()같이 Recurse에 ( recursive그리고 **파이썬 3.5부터 지원).
— Martijn Pieters


2

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

17
dirchache 는 "버전 2.6부터 사용되지 않습니다 : dircache 모듈이 Python 3.0에서 제거되었습니다."
— Daniel Reis
당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.