回答:
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')
if name in file or name in dirs
for name in files:失敗します。(私の人生の1時間、私は戻ってきたいです;-)やや厄介な修正はsuper-photo.jpgsuper-photo.JPGif str.lower(name) in [x.lower() for x in files]
のバージョンを使用したos.walkところ、より大きなディレクトリで3.5秒ほど時間がかかりました。私は2つのランダムなソリューションを試しましたが、大きな改善はありませんでした。
paths = [line[2:] for line in subprocess.check_output("find . -iname '*.txt'", shell=True).splitlines()]
POSIXのみですが、0.25秒かかりました。
このことから、プラットフォームに依存しない方法で検索全体を大幅に最適化することは完全に可能であると私は信じていますが、ここで私は研究をやめました。
UbuntuでPythonを使用していて、UbuntuでのみPythonを動作させたい場合は、端末の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倍高速であり、1回の検索で約72,000倍高速でした。
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に依存しない高速検索には、 scandir
https://github.com/benhoyt/scandir/#readme
読むhttp://bugs.python.org/issue11406をする理由の詳細については。
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"])
答えは既存のものと非常に似ていますが、わずかに最適化されています。
したがって、パターンでファイルやフォルダを見つけることができます。
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)
)
ファイルのみまたはフォルダのみを検索するには-たとえば、必要に応じて、「dirs + files」を「dirs」のみまたは「files」のみに置き換えます。
よろしく。
SARoseの答えは、Ubuntu 20.04 LTSから更新するまで機能しました。彼のコードを少し変更しただけで、最新のUbuntuリリースで動作します。
import subprocess
def find_files(file_name):
file_name = 'chromedriver'
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