পাইথনে একটি ফাইল সন্ধান করুন


110

আমার কাছে একটি ফাইল রয়েছে যা প্রতিটি ব্যবহারকারীর মেশিনে আলাদা জায়গায় থাকতে পারে। ফাইলটির জন্য কোনও অনুসন্ধান কার্যকর করার কোনও উপায় আছে? এমন কোনও উপায়ে যা আমি অনুসন্ধান করতে ফাইলের নাম এবং ডিরেক্টরি ট্রিটি পাস করতে পারি?


দেখুন OS মডিউল os.walk জন্য অথবা os.listdir দেখুন এই প্রশ্নের stackoverflow.com/questions/229186/... নমুনা কোড জন্য
মার্টিন বেকেট

উত্তর:


251

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

2
নোট করুন যে এই উদাহরণগুলি কেবল ফাইলগুলিই খুঁজে পাবে, একই নামের ডিরেক্টরিগুলি নয়। আপনি যদি সেই নামের সাথে ডিরেক্টরিতে কোনও বস্তু সন্ধান করতে চান তবে আপনি এটি ব্যবহার করতে চাইতে পারেনif name in file or name in dirs
মার্ক ই। হ্যামিল্টন

9
কেস সংবেদনশীলতা সম্পর্কে সাবধান। এটি ফাইল সিস্টেমে কখন রয়েছে তা for name in files:ব্যর্থ হবে । (আমার জীবনের এক ঘন্টা আমি ফিরে চাই ;-) কিছুটা অগোছালো সমাধান হ'লsuper-photo.jpgsuper-photo.JPGif str.lower(name) in [x.lower() for x in files]
ম্যাট উইলকি

ফলাফল তালিকা তৈরির পরিবর্তে ফলন ব্যবহার সম্পর্কে কী ? ..... যদি fnmatch.fnmatch (নাম, প্যাটার্ন): ফলন os.path.join (মূল, নাম)
বার্সি

দয়া করে পাইথন 3.x
আদিমগুলিতে

1
সংক্ষিপ্ত তালিকা ফাংশনটি প্রতিস্থাপন করতে পারে, যেমন: find_all: res = [os.path.join (root, name) for root, dirs, os.walk এ ফাইলগুলি (পাথ) ফাইলের নাম থাকলে]
নীড়

23

আমি একটি সংস্করণ ব্যবহার করেছি os.walkএবং বৃহত্তর ডিরেক্টরিতে প্রায় 3.5 সেকেন্ডের কাছাকাছি সময় পেয়েছি। আমি কোনও দুর্দান্ত উন্নতি না করে দুটি এলোমেলো সমাধান চেষ্টা করেছি, ঠিক তখনি করেছি:

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

এটি কেবল পসিক্স-এর মধ্যেই আমি 0.25 সেকেন্ড পেয়েছি।

এ থেকে, আমি বিশ্বাস করি যে প্ল্যাটফর্ম-স্বতন্ত্র উপায়ে পুরো অনুসন্ধানকে প্রচুর অনুকূলিতকরণ করা সম্পূর্ণভাবে সম্ভব, তবে এখান থেকেই আমি গবেষণাটি থামিয়ে দিয়েছি।


6

আপনি যদি উবুন্টুতে পাইথন ব্যবহার করে থাকেন এবং আপনি কেবল উবুন্টুতে এটির কাজ করতে চান তবে এটি টার্মিনালের locateপ্রোগ্রামটির মতো ব্যবহার is

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 গুণ বেশি দ্রুত করেছি।


5

পাইথন ৩.৪ বা তার চেয়েও নতুন আপনি পুনরাবৃত্ত গ্লোব্বিং করতে পাথলিব ব্যবহার করতে পারেন:

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


3

দ্রুত, ওএস-স্বাধীন অনুসন্ধানের জন্য, ব্যবহার করুন scandir

https://github.com/benhoyt/scandir/#readme

কেন তা বিশদ জানতে http://bugs.python.org/issue11406 পড়ুন ।


7
বিশেষত scandir.walk()@ নাদিয়ার উত্তর প্রতি ব্যবহার করুন । মনে রাখবেন যে আপনি যদি পাইথন 3.5+ ব্যবহার করেন os.walk()তবে এর scandir.walk()স্পিডআপগুলি ইতিমধ্যে রয়েছে। এছাড়াও, পিইপি 471 সম্ভবত এই ইস্যুটির চেয়ে তথ্যের জন্য পড়ার জন্য আরও ভাল নথি।
বেন হোয়েট

3

আপনি যদি পাইথন 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"])

2

নীচে আমরা প্রথম ম্যাচ এবং সমস্ত ম্যাচের মধ্যে স্যুইচ করতে একটি বুলিয়ান "প্রথম" যুক্তি ব্যবহার করি (একটি ডিফল্ট যা "সন্ধান করুন-নাম ফাইল" এর সমতুল্য):

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 

0

উত্তরটি বিদ্যমানগুলির সাথে খুব মিল, তবে কিছুটা অনুকূলিত হয়েছে।

সুতরাং আপনি প্যাটার্ন অনুসারে কোনও ফাইল বা ফোল্ডার খুঁজে পেতে পারেন:

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

কেবল ফাইল বা কেবল ফোল্ডার অনুসন্ধান করতে - আপনার প্রয়োজনীয়তার উপর নির্ভর করে "ডায়ার + ফাইল" প্রতিস্থাপন করুন, উদাহরণস্বরূপ, কেবল "ডায়ার" বা কেবল "ফাইল" দিয়ে।

শুভেচ্ছা।


0

আমি উবুন্টু 20.04 এলটিএস থেকে আপডেট না হওয়া পর্যন্ত সরোসের উত্তর আমার পক্ষে কাজ করেছে। আমি তার কোডে সামান্য পরিবর্তন এনেছি এটি সর্বশেষতম উবুন্টু মুক্তির কাজ করে।

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
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.