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


답변:


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에서 oslistdir()함수를 사용하여 현재 디렉토리의 파일 만 검색하는 간단한 방법입니다. 추가 탐색에서는 디렉토리의 폴더를 반환하는 방법을 보여 주지만 하위 디렉토리에는 파일이 없습니다. 걷기를 사용할 수 있습니다-나중에 설명).

 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 ) 내가 그들을하겠습니다 ( 파이썬이 가능한 준수, 또한, 어떤 코드에 속하는 게시 할 Pythonv3.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 dirent64ctypes 표현 입니다. 내 컴퓨터의 dirent.h (0P) ( DT_ 상수도 마찬가지 임) : Ubtu 16 x64 ( 4.10.0-40-genericlibc6-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.listdiros.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.