programing

파이썬에서 파일 찾기

projobs 2023. 6. 23. 23:42
반응형

파이썬에서 파일 찾기

각 사용자의 컴퓨터에서 다른 위치에 있을 수 있는 파일이 있습니다.파일 검색을 구현할 수 있는 방법이 있습니까?검색할 파일의 이름과 디렉터리 트리를 전달할 수 있는 방법은 무엇입니까?

os.walk가 정답입니다. 첫 번째 일치 항목을 찾습니다.

import os

def find(name, path):
    for root, dirs, files in os.walk(path):
        if name in files:
            return os.path.join(root, name)

그러면 모든 일치 항목이 검색됩니다.

def find_all(name, path):
    result = []
    for root, dirs, files in os.walk(path):
        if name in files:
            result.append(os.path.join(root, name))
    return result

그리고 이것은 패턴과 일치합니다.

import os, fnmatch
def find(pattern, path):
    result = []
    for root, dirs, files in os.walk(path):
        for name in files:
            if fnmatch.fnmatch(name, pattern):
                result.append(os.path.join(root, name))
    return result

find('*.txt', '/path/to/dir')

Python 3.4 이상 버전에서는 pathlib를 사용하여 재귀적 글로빙을 수행할 수 있습니다.

>>> import pathlib
>>> sorted(pathlib.Path('.').glob('**/*.py'))
[PosixPath('build/lib/pathlib.py'),
 PosixPath('docs/conf.py'),
 PosixPath('pathlib.py'),
 PosixPath('setup.py'),
 PosixPath('test_pathlib.py')]

참조: https://docs.python.org/3/library/pathlib.html#pathlib.Path.glob

Python 3.5 이상에서는 다음과 같은 재귀적 글로빙도 수행할 수 있습니다.

>>> import glob
>>> glob.glob('**/*.txt', recursive=True)
['2.txt', 'sub/3.txt']

참조: https://docs.python.org/3/library/glob.html#glob.glob

의 버전을 사용했습니다.os.walk그리고 더 큰 디렉토리에서 약 3.5초의 시간을 얻었습니다.크게 개선되지 않은 두 가지 랜덤 솔루션을 시도한 후 다음과 같이 수행했습니다.

paths = [line[2:] for line in subprocess.check_output("find . -iname '*.txt'", shell=True).splitlines()]

POSIX 전용이지만 0.25초를 받았습니다.

이를 통해 플랫폼에 의존하지 않는 방식으로 전체 검색을 최적화하는 것이 완전히 가능하다고 생각하지만, 여기서 연구를 중단했습니다.

만약 당신이 Ubuntu에서 Python을 사용하고 있고 그것이 Ubuntu에서만 작동하기를 원한다면, 그것은 터미널의 사용입니다.locate이런 프로그램.

import subprocess

def find_files(file_name):
    command = ['locate', file_name]

    output = subprocess.Popen(command, stdout=subprocess.PIPE).communicate()[0]
    output = output.decode()

    search_results = output.split('\n')

    return search_results

search_results이다.list파일 경로의 절대값입니다.이는 위의 방법보다 10,000배 더 빠르며 한 번 검색했을 때는 ~72,000배 더 빠릅니다.

Python 2로 작업하는 경우 자체 참조 심볼 링크로 인한 창의 무한 재귀 문제가 발생합니다.

이 스크립트는 이러한 스크립트를 따르지 않습니다.이것은 에 따라 다릅니다!

import os
from scandir import scandir
import ctypes

def is_sym_link(path):
    # http://stackoverflow.com/a/35915819
    FILE_ATTRIBUTE_REPARSE_POINT = 0x0400
    return os.path.isdir(path) and (ctypes.windll.kernel32.GetFileAttributesW(unicode(path)) & FILE_ATTRIBUTE_REPARSE_POINT)

def find(base, filenames):
    hits = []

    def find_in_dir_subdir(direc):
        content = scandir(direc)
        for entry in content:
            if entry.name in filenames:
                hits.append(os.path.join(direc, entry.name))

            elif entry.is_dir() and not is_sym_link(os.path.join(direc, entry.name)):
                try:
                    find_in_dir_subdir(os.path.join(direc, entry.name))
                except UnicodeDecodeError:
                    print "Could not resolve " + os.path.join(direc, entry.name)
                    continue

    if not os.path.exists(base):
        return
    else:
        find_in_dir_subdir(base)

    return hits

파일 이름 목록의 파일을 가리키는 모든 경로가 포함된 목록을 반환합니다.용도:

find("C:\\", ["file1.abc", "file2.abc", "file3.abc", "file4.abc", "file5.abc"])

아래에서는 부울 "first" 인수를 사용하여 첫 번째 일치와 모든 일치 사이를 전환합니다(기본값은 "find . -name file"과 같습니다).

import  os

def find(root, file, first=False):
    for d, subD, f in os.walk(root):
        if file in f:
            print("{0} : {1}".format(file, d))
            if first == True:
                break 

답은 기존 답과 매우 비슷하지만 약간 최적화되어 있습니다.

따라서 패턴별로 파일 또는 폴더를 찾을 수 있습니다.

def iter_all(pattern, path):
    return (
        os.path.join(root, entry)
        for root, dirs, files in os.walk(path)
        for entry in dirs + files
        if pattern.match(entry)
    )

하위 문자열을 사용하여:

def iter_all(substring, path):
    return (
        os.path.join(root, entry)
        for root, dirs, files in os.walk(path)
        for entry in dirs + files
        if substring in entry
    )

또는 술어 사용:

def iter_all(predicate, path):
    return (
        os.path.join(root, entry)
        for root, dirs, files in os.walk(path)
        for entry in dirs + files
        if predicate(entry)
    )

파일만 검색하거나 폴더만 검색 - 예를 들어, 필요한 항목에 따라 "파일"만 또는 "파일"만 검색합니다.

안부 전해요.

우분투 20.04 LTS에서 업데이트하기 전까지는 SARose의 답변이 효과가 있었습니다.내가 그의 코드에 약간의 변경을 가했기 때문에 그것은 최신 Ubuntu 릴리스에서 작동합니다.

import subprocess

def find_files(file_name):
    command = ['locate'+ ' ' + file_name]
    output = subprocess.Popen(command, stdout=subprocess.PIPE, shell=True).communicate()[0]
    output = output.decode()
    search_results = output.split('\n')
    return search_results

@F.M.F.의 답변은 이 버전에 몇 가지 문제가 있어서 작동하도록 몇 가지 조정을 했습니다.

import os
from os import scandir
import ctypes

def is_sym_link(path):
    # http://stackoverflow.com/a/35915819
    FILE_ATTRIBUTE_REPARSE_POINT = 0x0400
    return os.path.isdir(path) and (ctypes.windll.kernel32.GetFileAttributesW(str(path)) & FILE_ATTRIBUTE_REPARSE_POINT)

def find(base, filenames):
    hits = []

    def find_in_dir_subdir(direc):
        content = scandir(direc)
        for entry in content:
            if entry.name in filenames:
                hits.append(os.path.join(direc, entry.name))

            elif entry.is_dir() and not is_sym_link(os.path.join(direc, entry.name)):
                try:
                    find_in_dir_subdir(os.path.join(direc, entry.name))
                except UnicodeDecodeError:
                    print("Could not resolve " + os.path.join(direc, entry.name))
                    continue
                except PermissionError:
                    print("Skipped " + os.path.join(direc, entry.name) + ". I lacked permission to navigate")
                    continue

    if not os.path.exists(base):
        return
    else:
        find_in_dir_subdir(base)

    return hits

파이썬 3에서 unicode()가 str()로 변경되어 저는 그 조정을 했습니다(8행).

또한 Permission Error에 (25행) 및 예외를 추가했습니다.이렇게 하면 액세스할 수 없는 폴더를 찾으면 프로그램이 중지되지 않습니다.

마지막으로, 저는 약간의 경고를 드리고 싶습니다.프로그램을 실행할 때 단일 파일/디렉토리를 찾더라도 목록으로 전달해야 합니다.그렇지 않으면 검색과 반드시 일치하지 않는 많은 답변을 얻을 수 있습니다.

사용 예:

찾기("C:\", ["파이썬", "숙제"])

또는

find("C:\\", ["숙제"])

그러나 예를 들어 find("C:\\", "숙제")는 원하지 않는 대답을 제공합니다.

제가 왜 이런 일이 일어나는지 안다고 말한다면 저는 거짓말일 것입니다.다시 말씀드리지만, 이 코드는 제 코드가 아니며, 작동하기 위해 필요한 조정을 했을 뿐입니다.모든 크레딧은 @F.M.F.로 보내져야 합니다.

언급URL : https://stackoverflow.com/questions/1724693/find-a-file-in-python

반응형