وبلاگ رسانگار
با ما حرفه ای باشید

سرور مجازی NVMe

پایتون: لیست فایل ها در یک فهرست

0 27
زمان لازم برای مطالعه: 6 دقیقه


من ترجیح می دهم با پایتون کار کنم زیرا یک زبان برنامه نویسی بسیار انعطاف پذیر است و به من اجازه می دهد تا به راحتی با سیستم عامل تعامل داشته باشم. این شامل توابع سیستم فایل نیز می شود. به سادگی لیست کردن فایل ها در یک دایرکتوری ماژول ها os، subprocess، fnmatch، و pathlib بیا تو بازی. راه حل های زیر روش استفاده موثر از این روش ها را نشان می دهد.

استفاده کردن os.walk()

این os ماژول حاوی لیست طولانی روش هایی است که با سیستم فایل و سیستم عامل سروکار دارند. یکی از آنها است walk()، که با راه رفتن درخت از بالا به پایین یا پایین به بالا، نام فایل ها را در یک درخت دایرکتوری تولید می کند (که تنظیمات پیش فرض از بالا به پایین است).

os.walk() لیستی از سه مورد را برمی گرداند. این شامل نام root فهرست، فهرستی از نام زیر شاخه ها، و فهرستی از نام فایل ها در فهرست فعلی. لیست 1 نشان می دهد که چگونه می توان این را تنها با سه خط کد نوشت. این با هر دو مفسر پایتون 2 و 3 کار می کند.

فهرست 1: عبور از فهرست فعلی با استفاده از os.walk()

import os

for root, dirs, files in os.walk("."):
    for filename in files:
        print(filename)

استفاده از خط فرمان از طریق Subprocess

توجه داشته باشید: در حالی که این یک روش معتبر برای فهرست کردن فایل‌ها در یک فهرست است، اما توصیه نمی‌شود زیرا فرصت حملات تزریق دستور را معرفی می‌کند.

همانطور که قبلاً در مقاله پردازش موازی در پایتون توضیح داده شد subprocess ماژول به شما امکان می دهد یک فرمان سیستم را اجرا کنید و نتیجه آن را جمع آوری کنید. دستور سیستمی که در این مورد فراخوانی می کنیم به صورت زیر است:

مثال 1: فهرست کردن فایل‌ها در فهرست فعلی

$ ls -p . | grep -v /$

دستور ls -p . فایل های دایرکتوری را برای فهرست فعلی فهرست می کند و جداکننده را اضافه می کند / در انتهای نام هر زیر شاخه که در مرحله بعد به آن نیاز خواهیم داشت. خروجی این تماس به grep دستوری که داده ها را همانطور که ما نیاز داریم فیلتر می کند.

پارامترها -v /$ تمام نام ورودی هایی که به جداکننده ختم می شوند را حذف کنید /. در حقیقت، /$ یک عبارت منظم است که با تمام رشته های حاوی کاراکتر مطابقت دارد / به عنوان آخرین کاراکتر قبل از پایان رشته که با نشان داده می شود $.

این subprocess ماژول اجازه می دهد تا لوله های واقعی بسازید و جریان های ورودی و خروجی را همانطور که انجام می دهید متصل کنید روی یک خط فرمان فراخوانی روش subprocess.Popen() مربوطه را باز می کند process، و دو پارامتر نامگذاری شده را تعریف می کند stdin و stdout.

لیست 2 روش برنامه ریزی آن را نشان می دهد. متغیر اول ls به عنوان a تعریف می شود process اجرا کردن ls -p . که به یک لوله خروجی می دهد. به همین دلیل کانال stdout به صورت تعریف شده است subprocess.PIPE. متغیر دوم grep به عنوان a تعریف می شود process، نیز، اما دستور را اجرا می کند grep -v /$، بجای.

پیشنهاد می‌کنیم بخوانید:  محاسبه فاکتوریل با جاوا اسکریپت - تکراری و بازگشتی فاکتوریل یک عدد حاصل ضرب آن عدد صحیح و تمام اعداد صحیح مثبت کوچکتر یا مساوی با آن است. باید یک عدد صحیح مثبت باشد - در غیر این صورت، منطق تا بی نهایت منفی گسترش می یابد. به عبارت دیگر - محاسبه فاکتوریل به معنای ضرب کل کل ...

برای خواندن خروجی از ls فرمان از لوله، کانال stdin از grep به عنوان … تعریف شده است ls.stdout. در نهایت، متغیر endOfPipe خروجی را می خواند grep از جانب grep.stdout که از نظر عنصر در stdout چاپ می شود for-حلقه زیر خروجی در دیده می شود مثال 2.

فهرست 2: تعریف دو فرآیند مرتبط با یک لوله

import subprocess


ls = subprocess.Popen(("ls", "-p", "."),
                      stdout=subprocess.PIPE,
                     )


grep = subprocess.Popen(("grep", "-v", "/$"),
                        stdin=ls.stdout,
                        stdout=subprocess.PIPE,
                        )


endOfPipe = grep.stdout


for line in endOfPipe:
    print (line)

مثال 2: اجرای برنامه

$ python find-files3.py
find-files2.py
find-files3.py
find-files4.py
...

این راه حل با پایتون 2 و 3 کاملاً خوب کار می کند، اما آیا می توانیم به نحوی آن را بهبود بخشیم؟ اجازه دهید نگاهی به انواع دیگر داشته باشیم.

ترکیب کردن os و fnmatch

همانطور که قبلاً دیدید راه حل استفاده از فرآیندهای فرعی ظریف است اما به کدهای زیادی نیاز دارد. در عوض، اجازه دهید روش های دو ماژول را ترکیب کنیم os، و fnmatch. این نوع با پایتون 2 و 3 نیز کار می کند.

به عنوان اولین قدم، ما import دو ماژول os، و fnmatch. در مرحله بعد، دایرکتوری را که می‌خواهیم فایل‌ها را فهرست کنیم، تعریف می‌کنیم os.listdir()و همچنین الگوی فیلتر کردن فایل‌ها. در یک for حلقه را روی لیست ورودی های ذخیره شده در متغیر تکرار می کنیم listOfFiles.

در نهایت با کمک fnmatch ما برای ورودی هایی که به دنبال آن هستیم فیلتر می کنیم، و print ورودی های مطابق با stdout. لیست 3 شامل اسکریپت پایتون و مثال 3 خروجی مربوطه

لیست 3: لیست کردن فایل ها با استفاده از ماژول os و fnmatch

import os, fnmatch

listOfFiles = os.listdir('.')
pattern = "*.py"
for entry in listOfFiles:
    if fnmatch.fnmatch(entry, pattern):
            print (entry)

مثال 3: خروجی لیست 3

$ python2 find-files.py
find-files.py
find-files2.py
find-files3.py
...

استفاده کردن os.listdir() و ژنراتورها

به عبارت ساده، یک مولد یک تکرار کننده قدرتمند است که وضعیت خود را حفظ می کند. برای کسب اطلاعات بیشتر در مورد ژنراتورها، یکی از مقالات قبلی ما، مولدهای پایتون را بررسی کنید.

نوع زیر ترکیبی از listdir() روش از os ماژول با عملکرد ژنراتور این کد با هر دو نسخه 2 و 3 پایتون کار می کند.

همانطور که ممکن است قبلاً اشاره کرده باشید، listdir() متد لیست ورودی های دایرکتوری داده شده را برمی گرداند. روش os.path.isfile() برمی گرداند True اگر ورودی داده شده یک فایل باشد. این yield اپراتور از تابع خارج می شود اما وضعیت فعلی را حفظ می کند و فقط نام ورودی شناسایی شده را به عنوان یک فایل برمی گرداند. این به ما اجازه می دهد تا روی تابع مولد حلقه بزنیم (نگاه کنید به لیست 4). خروجی مشابه خروجی از است مثال 3.

فهرست 4: ترکیب os.listdir() و یک تابع ژنراتور

import os

def files(path):
    for file in os.listdir(path):
        if os.path.isfile(os.path.join(path, file)):
            yield file

for file in files("."):
    print (file)

استفاده کنید pathlib

این pathlib ماژول خود را به عنوان راهی برای “تجزیه، ساخت، تست و در غیر این صورت کار” توصیف می کند روی نام فایل ها و مسیرها با استفاده از API شی گرا به جای عملیات رشته های سطح پایین”.

که در لیست 5، ابتدا دایرکتوری را تعریف می کنیم. نقطه (“.”) دایرکتوری فعلی را تعریف می کند. بعد، iterdir() متد یک تکرار کننده را برمی گرداند که نام همه فایل ها را به دست می دهد. در یک for حلقه ما print نام فایل ها یکی پس از دیگری

پیشنهاد می‌کنیم بخوانید:  عملگر شرطی سه تایی پایتون

فهرست 5: خواندن محتویات دایرکتوری با pathlib

import pathlib


currentDirectory = pathlib.Path('.')

for currentFile in currentDirectory.iterdir():
    print(currentFile)

باز هم، خروجی با خروجی یکسان است مثال 3.

به عنوان جایگزین، می‌توانیم فایل‌ها را با تطبیق نام فایل‌ها با استفاده از چیزی به نام a بازیابی کنیم کره. به این ترتیب ما فقط می توانیم فایل های مورد نظر خود را بازیابی کنیم. به عنوان مثال، در کد زیر فقط می‌خواهیم فایل‌های پایتون را در فهرست خود فهرست کنیم که با مشخص کردن «*» این کار را انجام می‌دهیم.py”در جهان.

فهرست 6: استفاده از pathlib با glob روش

import pathlib


currentDirectory = pathlib.Path('.')


currentPattern = "*.py"

for currentFile in currentDirectory.glob(currentPattern):
    print(currentFile)

استفاده کردن os.scandir()

در پایتون 3.6، یک روش جدید در دسترس می شود os مدول. نامگذاری شده است scandir()، و به طور قابل توجهی فراخوانی برای فهرست کردن فایل ها در یک فهرست را ساده می کند.

با وارد کردن os ابتدا از ماژول استفاده کنید getcwd() روشی برای شناسایی دایرکتوری فعلی کار، و ذخیره این مقدار در path متغیر. بعد، scandir() فهرستی از ورودی‌های این مسیر را برمی‌گرداند که ما آن را برای فایل بودن با استفاده از آن آزمایش می‌کنیم is_file() روش.

فهرست 7: خواندن محتویات دایرکتوری با scandir()

import os


path = os.getcwd()


with os.scandir(path) as listOfEntries:
    for entry in listOfEntries:
        
        if entry.is_file():
            print(entry.name)

باز هم، خروجی از لیست 7 یکسان است با یکی از مثال 3.

نتیجه

اختلاف نظر وجود دارد که کدام نسخه بهترین است، کدام زیباترین و کدام “پایتونیک” ترین است. من سادگی را دوست دارم os.walk() روش و همچنین استفاده از هر دو fnmatch و pathlib ماژول ها

دو نسخه با فرآیند/پایپینگ و تکرارکننده نیاز به درک عمیق تری از فرآیندهای یونیکس و دانش پایتون دارند، بنابراین ممکن است به دلیل پیچیدگی اضافه (و غیر ضروری) برای همه برنامه نویسان بهترین نباشند.

برای یافتن پاسخی به اینکه کدام نسخه سریعترین است، timeit ماژول کاملا مفید است. این ماژول زمان سپری شده بین دو رویداد را شمارش می کند.

برای مقایسه همه راه‌حل‌های خود بدون تغییر آن‌ها، از یک عملکرد پایتون استفاده می‌کنیم: مفسر پایتون را با نام ماژول فراخوانی می‌کنیم و کد پایتون مناسب را برای اجرا می‌خوانیم. برای انجام این کار برای همه اسکریپت های پایتون به طور همزمان یک اسکریپت پوسته کمک می کند (فهرست 8).

فهرست 8: ارزیابی زمان اجرا با استفاده از timeit مدول

#! /bin/bash

for filename in *.py; do
    echo "$filename:"
    cat $filename | python3 -m timeit
    echo " "
done

تست ها با استفاده از Python 3.5.3 انجام شد. نتیجه به شرح زیر است در حالی که os.walk() بهترین نتیجه را می دهد. اجرای تست ها با پایتون 2 مقادیر متفاوتی را برمی گرداند اما ترتیب را تغییر نمی دهد – os.walk() هنوز هست روی بالای لیست

روش نتیجه برای 100,000,000 حلقه
os.walk 0.0085 usc در هر حلقه
زیر فرآیند/لوله 0.00859 usc در هر حلقه
os.listdir/fnmatch 0.00912 usc در هر حلقه
os.listdir/generator 0.00867 usc در هر حلقه
pathlib 0.00854 usc در هر حلقه
pathlib/glob 0.00858 usc در هر حلقه
os.scandir 0.00856 usc در هر حلقه

سپاسگزاریها

نویسنده مایل است تشکر کند جرولد روپرشت برای حمایت و نظرات او در حین تهیه این مقاله.

(برچسب‌ها به ترجمه)# python



منتشر شده در 1403-01-29 16:55:03

امتیاز شما به این مطلب
دیدگاه شما در خصوص مطلب چیست ؟

آدرس ایمیل شما منتشر نخواهد شد.

لطفا دیدگاه خود را با احترام به دیدگاه های دیگران و با توجه به محتوای مطلب درج کنید