একটি ডিরেক্টরিতে ফাইলগুলির একটি ফিল্টার তালিকা পান


281

আমি পাইথন ব্যবহার করে একটি ডিরেক্টরিতে ফাইলগুলির একটি তালিকা পাওয়ার চেষ্টা করছি, তবে আমি সমস্ত ফাইলের একটি তালিকা চাই না।

আমি মূলত যা চাই তা হ'ল পাইথন ব্যবহার করে এবং ls প্রয়োগ না করে নিম্নলিখিতগুলির মতো কিছু করার ক্ষমতা।

ls 145592*.jpg

যদি এর জন্য কোনও অন্তর্নির্মিত পদ্ধতি না থাকে তবে আমি বর্তমানে একটি ফলাফলের মাধ্যমে পুনরাবৃত্তি os.listdir()করতে এবং সমস্ত মিলে যাওয়া ফাইলগুলিকে একটি নতুন তালিকায় যুক্ত করার জন্য লুপের জন্য লিখার কথা ভাবছি ।

তবে সেই ডিরেক্টরিতে প্রচুর ফাইল রয়েছে এবং তাই আমি আশা করছি আরও কার্যকর পদ্ধতি আছে (বা একটি বিল্ট-ইন পদ্ধতি))


[এই লিঙ্কটি সাহায্য করতে পারে আপনি :) একটি ফিল্টার একটি ডিরেক্টরির মধ্যে ফাইলের তালিকা করুন] ( codereview.stackexchange.com/a/33642 )
sha111

মনে রাখবেন যে এটি যদি আপনার অ্যাপ্লিকেশনটির জন্য গুরুত্বপূর্ণ হয় তবে আপনি অর্ডার বাছাইয়ের বিষয়ে বিশেষ যত্ন নিতে পারেন।
লম্ব্রিক

উত্তর:


385

21
ওহ, আমি কেবল লক্ষ্য করেছি যে পাইথন ডকস বলে গ্লোব () "কনসার্টে os.listdir () এবং fnmatch.fnmatch () ফাংশনগুলি ব্যবহার করে করা হয়, এবং প্রকৃতপক্ষে সাবসেলের সাহায্যে নয়"। অন্য কথায়, গ্লোব () এর দক্ষতা উন্নতি নেই যার আশা করা যায়।
বেন হোয়েট

5
একটি প্রধান পার্থক্য রয়েছে: glob.glob('145592*.jpg')ফাইলগুলির সম্পূর্ণ নিখুঁত পথ ls 145592*.jpgমুদ্রণ করে কেবল ফাইলগুলির তালিকা মুদ্রণ করে।
আইজাক

8
@ বেন কেন সাবসেল (সাবপ্রসেস) চাওয়ার কোনও দক্ষতার উন্নতি হবে?
পাওলো নেভেস

7
@ পাওলোনিভস: সত্য, আমার আমার উপরের মন্তব্যটি years বছর পরে আমার কাছে বোধগম্য নয়। :-) আমি অনুমান করছি যে আমি glob()ওয়াইল্ডকার্ড ফিল্টারিংয়ের জন্য বিশেষ অপারেটিং সিস্টেমের কলের চেয়ে কেবল তালিকার + fnmatch ব্যবহার করি। উদাহরণস্বরূপ, উইন্ডোজ FindFirstFileএপিআই আপনাকে ওয়াইল্ডকার্ড নির্দিষ্ট করার অনুমতি দেয় যাতে ওএস সরাসরি ফিল্টারিং করে এবং সম্ভবত আরও দক্ষতার সাথে (আমি লিনাক্সের সমতুল্য বলে মনে করি না)।
বেন হোয়েট

1
@ মার্শ: বরাবরের মতো, প্রক্রিয়াটির বর্তমান ওয়ার্কিং ডিরেক্টরি।
Ignacio Vazquez-Abram

124

glob.glob()অবশ্যই এটি করার উপায় (Ignacio অনুযায়ী)। তবে আপনার যদি আরও জটিল মিলের প্রয়োজন হয় তবে আপনি এটি তালিকা বোধ এবং এটির re.match()মতো কিছু দিয়ে করতে পারেন:

files = [f for f in os.listdir('.') if re.match(r'[0-9]+.*\.jpg', f)]

আরও নমনীয়, কিন্তু আপনি নোট হিসাবে, কম দক্ষ।


এটি অবশ্যই আরও শক্তিশালী বলে মনে হচ্ছে। উদাহরণস্বরূপ, ভালো কিছু করতে না থাকার[0-9]+
demongolem

3
হ্যাঁ, অবশ্যই আরও শক্তিশালী - তবে fnmatch [0123456789]সিকোয়েন্সগুলি সমর্থন করে ( ডক্স দেখুন ), এবং এতে fnmatch.filter()ফাংশন রয়েছে যা এই লুপটিকে কিছুটা দক্ষ করে তোলে।
বেন হোয়েট

49

সহজবোধ্য রাখো:

import os
relevant_path = "[path to folder]"
included_extensions = ['jpg','jpeg', 'bmp', 'png', 'gif']
file_names = [fn for fn in os.listdir(relevant_path)
              if any(fn.endswith(ext) for ext in included_extensions)]

আমি তালিকা বোধের এই ফর্মটি পছন্দ করি কারণ এটি ইংরেজিতে ভাল পড়ে।

আমি এই হিসাবে চতুর্থ লাইনটি পড়েছি: আমার পথের জন্য os.listdir এ প্রতিটি fn এর জন্য, আমাকে কেবল আমার অন্তর্ভুক্ত এক্সটেনশনের কোনওটির সাথে মেলে give

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

এই নকশার একমাত্র জিনিস এটি তালিকার পরিবর্তে স্ট্রিং পাস করার ভুল করার বিরুদ্ধে আপনাকে রক্ষা করে না। উদাহরণস্বরূপ, যদি আপনি দুর্ঘটনাক্রমে একটি স্ট্রিংকে একটি তালিকায় রূপান্তর করেন এবং একটি স্ট্রিংয়ের সমস্ত অক্ষরের বিরুদ্ধে চেকিং শেষ করেন, তবে আপনি বেশ কয়েকটি মিথ্যা ধনাত্মক হয়ে উঠতে পারেন।

তবে বোঝার জন্য সহজ সমাধানের চেয়ে সমস্যা সমাধান করা সহজ।


5
any()এখানে কোনও প্রয়োজন নেই তা নয় , কারণ শেষের ক্রমstr.endswith() লাগে । যথেষ্ট চেয়ে বেশি। if fn.endswith(included_extentensions)
মার্টিজন পিটারস

3
str.endswith(seq)মার্তিজান উল্লেখ করেছেন যে এটি ব্যবহার না করার অদক্ষতা ছাড়াও , এটি সঠিক নয়, কারণ কোনও .extএক্সটেনশন থাকার জন্য কোনও ফাইলের সমাপ্তি ঘটে । এই কোডটি "উদাহরণস্বরূপ" "myjpg" নামক একটি ফাইল বা "png" নামের একটি ডিরেক্টরিও খুঁজে পাবে। ঠিক করতে, প্রতিটি এক্সটেনশানটি কেবল included_extensionsএকটি দিয়ে প্রিফিক্স করুন .
বেন হোয়েট

আমি উত্তরগুলিতে সর্বদা কোড থেকে কিছুটা সতর্ক থাকি যা স্পষ্টতই চালানো হয়নি বা চালাতে পারে না। চলক included_extensionsবনাম included_extentsions? দুঃখের কারণ অন্যথায় এটি আমার পছন্দসই উত্তর।
অ্যাসপিস

39

অন্য বিকল্প:

>>> import os, fnmatch
>>> fnmatch.filter(os.listdir('.'), '*.py')
['manage.py']

https://docs.python.org/3/library/fnmatch.html


5
globএক লাইনে ঠিক এটিই ঘটে।
Itay গ্রুদেব

কেবলমাত্র ফাইলের নাম ফিরিয়ে দেওয়ার globবিপরীতে কেবলমাত্র পার্থক্যই পুরো পথটি os.listdirদেয়। অন্তত এই কি পাইথন 2. ঘটছে তা হয়
Karthic Raghupathi

17

globমডিউল সহ ফিল্টার :

আমদানি গ্লোব

import glob

ওয়াইল্ড কার্ড:

files=glob.glob("data/*")
print(files)

Out:

['data/ks_10000_0', 'data/ks_1000_0', 'data/ks_100_0', 'data/ks_100_1',
'data/ks_100_2', 'data/ks_106_0', 'data/ks_19_0', 'data/ks_200_0', 'data/ks_200_1', 
'data/ks_300_0', 'data/ks_30_0', 'data/ks_400_0', 'data/ks_40_0', 'data/ks_45_0', 
'data/ks_4_0', 'data/ks_500_0', 'data/ks_50_0', 'data/ks_50_1', 'data/ks_60_0', 
'data/ks_82_0', 'data/ks_lecture_dp_1', 'data/ks_lecture_dp_2']

ফিটার এক্সটেনশন .txt:

files = glob.glob("/home/ach/*/*.txt")

একক চরিত্র

glob.glob("/home/ach/file?.txt")

সংখ্যা ব্যাপ্তি

glob.glob("/home/ach/*[0-9]*")

বর্ণমালা রেঞ্জ

glob.glob("/home/ach/[a-c]*")

12

প্রাথমিক কোড

import glob
import fnmatch
import pathlib
import os

pattern = '*.py'
path = '.'

সমাধান 1 - "গ্লোব" ব্যবহার করুন

# lookup in current dir
glob.glob(pattern)

In [2]: glob.glob(pattern)
Out[2]: ['wsgi.py', 'manage.py', 'tasks.py']

সমাধান 2 - "ওএস" + "এফএনমেচ" ব্যবহার করুন

বৈকল্পিক 2.1 - বর্তমান দিরের দিকে তাকান

# lookup in current dir
fnmatch.filter(os.listdir(path), pattern)

In [3]: fnmatch.filter(os.listdir(path), pattern)
Out[3]: ['wsgi.py', 'manage.py', 'tasks.py']

বৈকল্পিক 2.2 - পুনরাবৃত্তির চেহারা দেখুন

# lookup recursive
for dirpath, dirnames, filenames in os.walk(path):

    if not filenames:
        continue

    pythonic_files = fnmatch.filter(filenames, pattern)
    if pythonic_files:
        for file in pythonic_files:
            print('{}/{}'.format(dirpath, file))

ফলাফল

./wsgi.py
./manage.py
./tasks.py
./temp/temp.py
./apps/diaries/urls.py
./apps/diaries/signals.py
./apps/diaries/actions.py
./apps/diaries/querysets.py
./apps/library/tests/test_forms.py
./apps/library/migrations/0001_initial.py
./apps/polls/views.py
./apps/polls/formsets.py
./apps/polls/reports.py
./apps/polls/admin.py

সমাধান 3 - "প্যাথলিব" ব্যবহার করুন

# lookup in current dir
path_ = pathlib.Path('.')
tuple(path_.glob(pattern))

# lookup recursive
tuple(path_.rglob(pattern))

মন্তব্য:

  1. পাইথন ৩.৪-তে পরীক্ষা করা হয়েছে
  2. "পাথলিব" মডিউলটি কেবল পাইথন ৩.৪-এ যুক্ত করা হয়েছিল
  3. পাইথন ৩.৫ গ্লোব . glob https://docs.python.org/3.5/library/glob.html#glob.glob এর সাথে পুনরাবৃত্ত অনুসন্ধানের জন্য একটি বৈশিষ্ট্য যুক্ত করেছে । যেহেতু আমার মেশিনটি পাইথন ৩.৪ এর সাথে ইনস্টল করা আছে, তাই আমি এটি পরীক্ষা করিনি।

9

আপনার ফাইলগুলি পুনরাবৃত্তভাবে তালিকাভুক্ত করতে os.walk ব্যবহার করুন

import os
root = "/home"
pattern = "145992"
alist_filter = ['jpg','bmp','png','gif'] 
path=os.path.join(root,"mydir_to_scan")
for r,d,f in os.walk(path):
    for file in f:
        if file[-3:] in alist_filter and pattern in file:
            print os.path.join(root,file)

টুকরো টুকরো করার দরকার নেই; file.endswith(alist_filter)যথেষ্ট।
মার্টিজন পিটারস

5
import os

dir="/path/to/dir"
[x[0]+"/"+f for x in os.walk(dir) for f in x[2] if f.endswith(".jpg")]

এটি আপনাকে তাদের পুরো পাথ সহ jpg ফাইলের একটি তালিকা দেবে। আপনি প্রতিস্থাপন করতে পারেন x[0]+"/"+fসঙ্গে fশুধু ফাইলের নামের জন্য। আপনি f.endswith(".jpg")যে স্ট্রিং শর্তটি চান তা প্রতিস্থাপন করতে পারেন ।


3

আপনি আরও উচ্চ-স্তরের পদ্ধতির পছন্দ করতে পারেন (আমি প্রয়োগ করেছি এবং ফাইন্ডলগুলি হিসাবে প্যাকেজ করেছি ):

from findtools.find_files import (find_files, Match)


# Recursively find all *.txt files in **/home/**
txt_files_pattern = Match(filetype='f', name='*.txt')
found_files = find_files(path='/home', match=txt_files_pattern)

for found_file in found_files:
    print found_file

সঙ্গে ইনস্টল করা যাবে

pip install findtools

2

"পাথ / টু / ইমেজ" এ "jpg" এবং "png" এক্সটেনশান সহ ফাইলের নাম:

import os
accepted_extensions = ["jpg", "png"]
filenames = [fn for fn in os.listdir("path/to/images") if fn.split(".")[-1] in accepted_extensions]

এটি @ ramsey0
chb

1

আপনি পাইথন ব্যবহার করতে পারেন যা পাইথন স্ট্যান্ডার্ড লাইব্রেরিতে ৩.৪ এবং তারপরের

from pathlib import Path

files = [f for f in Path.cwd().iterdir() if f.match("145592*.jpg")]

1

আপনি প্যাটার্নটি সংজ্ঞায়িত করতে পারেন এবং এটি পরীক্ষা করতে পারেন। এখানে আমি শুরু এবং শেষের প্যাটার্ন উভয়ই নিয়েছি এবং ফাইলের নামে তাদের সন্ধান করছি। ফাইলগুলিতে একটি ডিরেক্টরিতে থাকা সমস্ত ফাইলের তালিকা থাকে।

import os
PATTERN_START = "145592"
PATTERN_END = ".jpg"
CURRENT_DIR = os.path.dirname(os.path.realpath(__file__))
for r,d,FILES in os.walk(CURRENT_DIR):
    for FILE in FILES:
        if PATTERN_START in FILE and PATTERN_END in FILE:
            print FILE

0

Str.split () সম্পর্কে কীভাবে? আমদানির জন্য কিছুই নেই।

import os

image_names = [f for f in os.listdir(path) if len(f.split('.jpg')) == 2]

2
উত্তরটি জিপসির
সুশান্ত

এটি @ ramsey0 এর উত্তরের সাথে মিল বলে মনে হচ্ছে f.endswith('.jpg')(তবে এটিও নির্বাচন করবে filename.jpg.ext)
anjsimmo

-1

আপনি সাব-প্রসেস.সেক_উপুট () হিসাবে ব্যবহার করতে পারেন

import subprocess

list_files = subprocess.check_output("ls 145992*.jpg", shell=True) 

অবশ্যই, কোটের মধ্যে থাকা স্ট্রিং শেলটিতে আপনি কার্যকর করতে চান এমন কিছু হতে পারে এবং আউটপুট সংরক্ষণ করতে পারে।


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