از طریق منوی جستجو مطلب مورد نظر خود در وبلاگ را به سرعت پیدا کنید
پایتون: لیست فایل ها در یک فهرست
سرفصلهای مطلب
من ترجیح می دهم با پایتون کار کنم زیرا یک زبان برنامه نویسی بسیار انعطاف پذیر است و به من اجازه می دهد تا به راحتی با سیستم عامل تعامل داشته باشم. این شامل توابع سیستم فایل نیز می شود. به سادگی لیست کردن فایل ها در یک دایرکتوری ماژول ها 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