নীচের ডিরেক্টরিতে খনন না করে os.walk


103

আমি os.walkযে ডিরেক্টরিটি সরবরাহ করি কেবল তাতে ফাইলগুলি ফিরিয়ে দেওয়ার সীমা কীভাবে রাখব ?

def _dir_list(self, dir_name, whitelist):
    outputList = []
    for root, dirs, files in os.walk(dir_name):
        for f in files:
            if os.path.splitext(f)[1] in whitelist:
                outputList.append(os.path.join(root, f))
            else:
                self._email_to_("ignore")
    return outputList

2
সম্ভাব্য পন্থাগুলির প্রচুর সংখ্যা এবং তাদের সাথে যে সমস্ত সতর্কতা রয়েছে তা বোঝায় যে এই কার্যকারিতাটি পাইথন স্ট্যান্ডার্ড লাইব্রেরিতে যুক্ত করা উচিত।
antred

files_with_full_path = [f.path for f in os.scandir(dir) if f.is_file()]। যদি আপনার f.nameপরিবর্তে কেবলমাত্র ফাইলের নাম ব্যবহার করা প্রয়োজন f.path। এটি সবচেয়ে দ্রুত সমাধান এবং যেকোন walkবা এর থেকে অনেক দ্রুত listdir, দেখুন stackoverflow.com/a/40347279/2441026
ব্যবহারকারী 136036

উত্তর:


105

walklevelফাংশনটি ব্যবহার করুন ।

import os

def walklevel(some_dir, level=1):
    some_dir = some_dir.rstrip(os.path.sep)
    assert os.path.isdir(some_dir)
    num_sep = some_dir.count(os.path.sep)
    for root, dirs, files in os.walk(some_dir):
        yield root, dirs, files
        num_sep_this = root.count(os.path.sep)
        if num_sep + level <= num_sep_this:
            del dirs[:]

এটি ঠিক একইভাবে কাজ করে os.walkতবে আপনি এটি একটি levelপ্যারামিটারটি পাস করতে পারেন যা নির্দেশ করে যে পুনরাবৃত্তিটি কত গভীর হবে।


3
এই ফাংশনটি আসলে পুরো কাঠামোটির মধ্য দিয়ে "হাঁটাচলা" করে এবং তারপরে একটি নির্দিষ্ট পয়েন্টের নীচে প্রবেশগুলি মুছতে পারে? নাকি আরও কিছু চালাক চলছে? আমি কোড দিয়ে কীভাবে এটি চেক করব তাও নিশ্চিত নই। --পিথন শিক্ষানবিস
ম্যাথটিক

1
@ ম্যাথটিক: যখন কাঙ্ক্ষিত স্তরের বা নীচে কিছু ডিরেক্টরি পাওয়া যায়, এর অনুসন্ধানের জন্য তার সমস্ত সাবডারকে সাবডিয়ারের তালিকা থেকে সরানো হয়। সুতরাং তারা "হাঁটা" হবে না।
nosklo

2
আমি কেবল এটি +1 করেছি কারণ আমি কীভাবে ডায়ারগুলি "মুছুন" তা নিয়ে লড়াই করে যাচ্ছিলাম। আমি চেষ্টা করেছিলেন dirs = []এবং dirs = Noneকিন্তু যারা কাজ করে নি। map(dirs.remove, dirs)কাজ করেছে, তবে কিছু অযাচিত '[কিছুই নয়]' বার্তা মুদ্রিত হয়েছে। সুতরাং, কেন del dirs[:]বিশেষভাবে?
জ্যাচ ইয়াং

4
মনে রাখবেন যে topdown=Falseওএসওয়াক এ ব্যবহার করার সময় এটি কাজ করে না । দস্তাবেজগুলির মধ্যে চতুর্থ অনুচ্ছেদটি দেখুন :Modifying dirnames when topdown is False has no effect on the behavior of the walk, because in bottom-up mode the directories in dirnames are generated before dirpath itself is generated.
dthor

3
@ জাচারি ইয়ং dirs = []এবং dirs = Noneকাজ করবে না কারণ তারা কেবল একটি নতুন সম্পর্কযুক্ত অবজেক্ট তৈরি করে এবং নামটি বরাদ্দ করে dirs। আসল তালিকা অবজেক্টটি স্থানের পরিবর্তে প্রয়োজন, নাম নয় dirs
nosklo

206

Os.walk ব্যবহার করবেন না।

উদাহরণ:

import os

root = "C:\\"
for item in os.listdir(root):
    if os.path.isfile(os.path.join(root, item)):
        print item

1
@ 576i: এটি ফাইল এবং ডিরেক্টরিগুলির মধ্যে পার্থক্য করে না

4
@ আলেকজান্ডার os.path.isfileএবং os.path.isdirআপনাকে আলাদা করতে দেয়। আমি এটি পাই না, os.path.isfileযেহেতু '08 সাল থেকে নমুনা কোডে রয়েছে এবং আপনার মন্তব্যটি '16 থেকে। এটি স্পষ্টতই উত্তম উত্তর, কেননা আপনি কোনও ডিরেক্টরি চালনার উদ্দেশ্যে নয়, তবে এটি তালিকাভুক্ত করার জন্য।
ড্যানিয়েল এফ

@ ড্যানিয়েলএফ, আমি এখানে যা বোঝাতে চেয়েছি তা হ'ল আপনাকে সমস্ত আইটেমের উপর লুপ করা দরকার, যখন walkআপনাকে তাত্ক্ষণিক ডায়ার এবং ফাইলগুলির পৃথক তালিকা দেয়।

আহ, ঠিক আছে. আসলে অ্যালেক্সের উত্তরটি আরও ভাল (ব্যবহার করে .next()) বলে মনে হচ্ছে এবং এটি আপনার ধারণার অনেক কাছে।
ড্যানিয়েল এফ

পাইথন 3.5 এর একটি os.scandirফাংশন রয়েছে যা আরও পরিশীলিত ফাইল-বা ডিরেক্টরি-ডিরেক্টরি-অবজেক্ট মিথস্ক্রিয়াকে মঞ্জুরি দেয়। দেখুন আমার উত্তর নিচে
ascripter

48

আমি মনে করি সমাধানটি আসলে খুব সহজ।

ব্যবহার

break

লুপটির জন্য কেবল প্রথম পুনরাবৃত্তিটি করতে, আরও একটি মার্জিত উপায় থাকতে হবে।

for root, dirs, files in os.walk(dir_name):
    for f in files:
        ...
        ...
    break
...

প্রথমবার যখন আপনি ও.ওয়াককে কল করেন, এটি বর্তমান ডিরেক্টরিটির জন্য টিউলিপগুলি ফিরিয়ে দেয়, তারপরে পরবর্তী ডিরেক্টরিটির বিষয়বস্তুগুলির লুপে।

আসল স্ক্রিপ্ট নিন এবং কেবল একটি বিরতি যুক্ত করুন

def _dir_list(self, dir_name, whitelist):
    outputList = []
    for root, dirs, files in os.walk(dir_name):
        for f in files:
            if os.path.splitext(f)[1] in whitelist:
                outputList.append(os.path.join(root, f))
            else:
                self._email_to_("ignore")
        break
    return outputList

9
এটি গ্রহণযোগ্য উত্তর হওয়া উচিত ছিল। কেবল "ফাইলের জন্য এফ" ফাইলের পরে "বিরতি" যুক্ত করা পুনরাবৃত্তি থামিয়ে দেয়। আপনি যে শীর্ষস্থানীয় = সত্য তা নিশ্চিত করতেও পারেন।
আলেজ

23

ব্যবহারের পরামর্শটি listdirএকটি ভাল। পাইথন 2 এ আপনার প্রশ্নের সরাসরি উত্তর root, dirs, files = os.walk(dir_name).next()

পাইথন 3 সিনট্যাক্সের সমতুল্য root, dirs, files = next(os.walk(dir_name))


1
ওহ আমি সেই থেকে সমস্ত ধরণের মজার ত্রুটি পেয়েছিলাম। ভ্যালুএররার: আনপ্যাক করার জন্য অনেকগুলি মান
সেতুরি

1
নিস! যদিও হ্যাকের মতো মনে হচ্ছে। যেমন আপনি যখন ইঞ্জিন চালু করেন তবে কেবল একটি বিপ্লব করতে দিন এবং তারপরে এটি মারা যেতে চাবিটি টানুন।
ড্যানিয়েল এফ

এইজন্য হোঁচট খেয়েছে; root, dirs, files = os.walk(dir_name).next()আমাকে দেয়AttributeError: 'generator' object has no attribute 'next'
ইভান

3
@ ইভান, সম্ভবত এটি 2008 সালের এবং পাইথন 2 সিনট্যাক্স ব্যবহার করে uses পাইথন 3 এ আপনি লিখতে পারেন root, dirs, files = next(os.walk(dir_name))এবং তারপরে ভেরিয়েবলগুলি root, dirs, filesকেবলমাত্র dir_nameস্তরের জেনারেটরের ভেরিয়েবলগুলির সাথে মিল রাখে ।
সার্ভিড

13

আপনি os.listdir()কোনও প্রদত্ত ডিরেক্টরিতে নামের একটি তালিকা (ফাইল এবং ডিরেক্টরি উভয়ের জন্য) ফেরত ব্যবহার করতে পারেন । আপনার যদি ফাইল এবং ডিরেক্টরিগুলির মধ্যে পার্থক্য করতে os.stat()হয় তবে প্রতিটি নাম কল করুন।


9

আপনার যদি কেবল শীর্ষ ডিরেক্টরি (যেমন ভিসিএস ডায়ার ইত্যাদি উপেক্ষা করুন) এর চেয়ে আরও জটিল প্রয়োজনীয়তা থাকে তবে আপনি ওএস.ওয়াকের মাধ্যমে পুনরাবৃত্তি রোধ করতে ডিরেক্টরিগুলির তালিকাটিও সংশোধন করতে পারেন।

অর্থাৎ,

def _dir_list(self, dir_name, whitelist):
    outputList = []
    for root, dirs, files in os.walk(dir_name):
        dirs[:] = [d for d in dirs if is_good(d)]
        for f in files:
            do_stuff()

দ্রষ্টব্য - তালিকার পুনঃতফসিলের পরিবর্তে তালিকার পরিবর্তন করতে সাবধান হন। স্পষ্টতই ওএসওয়াক বাহ্যিক রিমন্ডিং সম্পর্কে জানেন না।




3

আমার 2 পেন্স ভিতরে likeুকানোর মতো মনে হয়েছে।

baselevel = len(rootdir.split("\\"))
for subdirs, dirs, files in os.walk(rootdir):
    curlevel = len(subdirs.split("\\"))
    if curlevel <= baselevel + 1:
        [do stuff]

2

পাইথন 3 এ, আমি এটি করতে পেরেছিলাম:

import os
dir = "/path/to/files/"

#List all files immediately under this folder:
print ( next( os.walk(dir) )[2] )

#List all folders immediately under this folder:
print ( next( os.walk(dir) )[1] )

এটি পাইথন 2 এর জন্যও কাজ করে the দ্বিতীয় স্তরটি কীভাবে পাবেন?

2

যেহেতু পাইথন 3.5 আপনি ব্যবহার করতে পারেন os.scandirপরিবর্তে os.listdir। স্ট্রিংয়ের পরিবর্তে আপনি বিনিময়ে DirEntryঅবজেক্টের একটি পুনরাবৃত্তি পাবেন । ডক্স থেকে:

scandir()পরিবর্তে ব্যবহার করা listdir()কোডের কার্যকারিতা উল্লেখযোগ্যভাবে বাড়িয়ে তুলতে পারে যার জন্য ফাইল টাইপ বা ফাইল বৈশিষ্ট্য সম্পর্কিত তথ্যও প্রয়োজন, কারণ DirEntryকোনও ডিরেক্টরি স্ক্যান করার সময় যদি অপারেটিং সিস্টেম এটি সরবরাহ করে তবে অবজেক্টগুলি এই তথ্য প্রকাশ করে। সমস্ত DirEntryপদ্ধতি একটি সিস্টেম কল করতে পারে, তবে is_dir()এবং is_file()সাধারণত প্রতীকী লিঙ্কগুলির জন্য কেবল একটি সিস্টেম কল প্রয়োজন; DirEntry.stat()সর্বদা ইউনিক্সে একটি সিস্টেম কল প্রয়োজন তবে উইন্ডোজে প্রতীকী লিঙ্কগুলির জন্য কেবল একটির প্রয়োজন।

আপনি সেই বস্তুর নাম অ্যাক্সেস করতে পারেন DirEntry.nameযার মাধ্যমে তারপরে আউটপুট সমানos.listdir


1
আপনি কেবল "ক্যান" ব্যবহার করেন না, আপনার ব্যবহার করা উচিতscandir() , কারণ এটি এর চেয়ে অনেক দ্রুত listdir()মানদণ্ডগুলি এখানে দেখুন: stackoverflow.com/a/40347279/2441026
ব্যবহারকারী 136036

1

আপনি নিম্নলিখিতগুলি করতে পারেন:

for path, subdirs, files in os.walk(dir_name):
    for name in files:
        if path == ".": #this will filter the files in the current directory
             #code here

2
অযথা সমস্ত সাব-ডির এবং ফাইলগুলির মধ্য দিয়ে এই লুপটি কী হবে না?
পিটার

0

এভাবেই সমাধান করেছি

if recursive:
    items = os.walk(target_directory)
else:
    items = [next(os.walk(target_directory))]

...

0

তালিকাবদ্ধ ব্যবহার করার সময় একটি ধরা আছে। Os.path.isdir (সনাক্তকারী) অবশ্যই একটি পরম পাথ be উপ-ডিরেক্টরি বাছাই করতে আপনি করুন:

for dirname in os.listdir(rootdir):
  if os.path.isdir(os.path.join(rootdir, dirname)):
     print("I got a subdirectory: %s" % dirname)

বিকল্পটি হল os.path.join () ছাড়াই টেস্টিংয়ের জন্য ডিরেক্টরিতে পরিবর্তন করা।


0

আপনি এই স্নিপেট ব্যবহার করতে পারেন

for root, dirs, files in os.walk(directory):
    if level > 0:
        # do some stuff
    else:
        break
    level-=1

0

বাদ দেওয়া একটি তালিকা তৈরি করুন, ডিরেক্টরি কাঠামো এড়াতে এবং প্রক্রিয়াটি করতে fnmatch ব্যবহার করুন

excludes= ['a\*\b', 'c\d\e']
for root, directories, files in os.walk('Start_Folder'):
    if not any(fnmatch.fnmatch(nf_root, pattern) for pattern in excludes):
        for root, directories, files in os.walk(nf_root):
            ....
            do the process
            ....

'অন্তর্ভুক্ত' হিসাবে একই:

if **any**(fnmatch.fnmatch(nf_root, pattern) for pattern in **includes**):

0

কেন নয় কেবল একটি ব্যবহার rangeএবং os.walkসঙ্গে মিলিত zip? সেরা সমাধান নয়, তবে কাজও করবে।

উদাহরণস্বরূপ:

# your part before
for count, (root, dirs, files) in zip(range(0, 1), os.walk(dir_name)):
    # logic stuff
# your later part

অজগর 3 এ আমার জন্য কাজ করে।

এছাড়াও: এ breakসরল খুব বিটিডব্লিউ। (@ পিটারের উত্তর দেখুন)


0

অ্যালেক্সের উত্তরে সামান্য পরিবর্তন, তবে ব্যবহার করে __next__():

print(next(os.walk('d:/'))[2]) অথবা print(os.walk('d:/').__next__()[2])

সঙ্গে [2]হচ্ছে fileমধ্যে root, dirs, fileঅন্যান্য উত্তর উল্লেখিত


0

প্রতিটি ডিরেক্টরিের জন্য রুট ফোল্ডার পরিবর্তন হয়। আমি রুট == ডিরেক্টরি কিনা তা যাচাই করেছিলাম

def _dir_list(self, dir_name, whitelist):
    outputList = []
    for root, dirs, files in os.walk(dir_name):
        if root == dir_name: #This only meet parent folder
            for f in files:
                if os.path.splitext(f)[1] in whitelist:
                    outputList.append(os.path.join(root, f))
                else:
                    self._email_to_("ignore")
    return outputList

0
import os

def listFiles(self, dir_name):
    names = []
    for root, directory, files in os.walk(dir_name):
        if root == dir_name:
            for name in files:
                names.append(name)
    return names

1
হাই রিচ, স্ট্যাক ওভারফ্লোতে আপনাকে স্বাগতম! এই কোড স্নিপেটের জন্য আপনাকে ধন্যবাদ, যা কিছু সীমিত স্বল্পমেয়াদী সহায়তা সরবরাহ করতে পারে। একটি সঠিক ব্যাখ্যা কেন এটি সমস্যার একটি ভাল সমাধান, তা দেখিয়ে তার দীর্ঘমেয়াদী মানকে ব্যাপকভাবে উন্নত করবে এবং ভবিষ্যতের পাঠকদের আরও অন্যান্য অনুরূপ প্রশ্নের সাথে আরও দরকারী করে তুলবে। আপনার অনুমানগুলি সহ কিছু ব্যাখ্যা যুক্ত করতে দয়া করে আপনার উত্তরটি সম্পাদনা করুন।
কেনে_কে
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.