मेरे पास एक फ़ाइल है जो प्रत्येक उपयोगकर्ता की मशीन पर एक अलग स्थान पर हो सकती है। क्या फ़ाइल की खोज को लागू करने का कोई तरीका है? ऐसा तरीका जिससे मैं खोज करने के लिए फ़ाइल का नाम और निर्देशिका ट्री पास कर सकूं?
मेरे पास एक फ़ाइल है जो प्रत्येक उपयोगकर्ता की मशीन पर एक अलग स्थान पर हो सकती है। क्या फ़ाइल की खोज को लागू करने का कोई तरीका है? ऐसा तरीका जिससे मैं खोज करने के लिए फ़ाइल का नाम और निर्देशिका ट्री पास कर सकूं?
जवाबों:
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:विफल रहेगा । (मेरे जीवन का एक घंटा मैं वापस चाहूंगा; ;-) कुछ गन्दा तय हैsuper-photo.jpgsuper-photo.JPGif str.lower(name) in [x.lower() for x in files]
मैंने एक संस्करण का उपयोग किया os.walkऔर एक बड़ी निर्देशिका पर लगभग 3.5 सेकंड का समय मिला। मैंने बिना किसी महान सुधार के दो यादृच्छिक समाधानों की कोशिश की, फिर बस:
paths = [line[2:] for line in subprocess.check_output("find . -iname '*.txt'", shell=True).splitlines()]
जबकि यह POSIX-only है, मुझे 0.25 सेकंड मिला है।
इससे, मेरा मानना है कि पूरी तरह से एक प्लेटफॉर्म-स्वतंत्र तरीके से पूरी खोज को अनुकूलित करना संभव है, लेकिन यह वह जगह है जहां मैंने शोध को रोक दिया है।
यदि आप उबंटू पर पायथन का उपयोग कर रहे हैं और आप केवल उबंटू पर काम करना चाहते हैं 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 गुना तेज किया।
पायथन 3.4 या नए में आप पुनरावर्ती ग्लोबिंग करने के लिए पैथलिब का उपयोग कर सकते हैं:
>>> 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
पायथन 3.5 या नए में आप इस तरह से पुनरावर्ती ग्लोबिंग भी कर सकते हैं:
>>> import glob
>>> glob.glob('**/*.txt', recursive=True)
['2.txt', 'sub/3.txt']
संदर्भ: https://docs.python.org/3/library/glob.html#glob.glob
तेजी से, ओएस-स्वतंत्र खोज के लिए, उपयोग करें scandir
https://github.com/benhoyt/scandir/#readme
विवरण के लिए http://bugs.python.org/issue11406 पढ़ें ।
यदि आप पायथन 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"])
नीचे हम पहले मैच और सभी मैचों के बीच स्विच करने के लिए एक बूलियन "पहले" तर्क का उपयोग करते हैं (एक डिफ़ॉल्ट जो "खोज -नाम फ़ाइल" के बराबर है):।
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)
)
केवल फ़ाइलों या केवल फ़ोल्डरों को खोजने के लिए - "dirs + files" को बदलें, उदाहरण के लिए, केवल "dirs" या केवल "files" के साथ, जो आपके लिए आवश्यक है।
सादर।
SARose का जवाब मेरे लिए तब तक काम करता था जब तक कि मैं Ubuntu 20.04 LTS से अपडेट नहीं हो जाता। मैंने उनके कोड में जो थोड़ा सा बदलाव किया, वह नवीनतम उबंटू रिलीज पर काम करता है।
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