بدست آوردن حجم یک مسیر در ترمینال [Python]
توسط: vahit
سلام
آدمی که داره برنامه نویسی یاد میگیره باید هر ایده و فکری به ذهنش رسید برنامش رو بنویسه حداقل باید تلاشش رو بکنه. از ریکد کردن یه بازی گرفته تا راه رفتن گربه رو دیوار.
پریروز میخواستم یه پوشه با حجم بالا به گوشی انتقال بدم که متوجه شدم یه حجم غیر باوری از فضای گوشی گرفته شده بدون اینکه من متوجه بشم. داشتم دنبال فایلهای اضافی بودم و به این که دستور ls نمیتونه حجم مسیرها رو نشون بده و فقط حجم فایلها رو نشون میده غر می زدم که یهو فکر کردم آیا غر زدن درسته؟! خب حجم پوشه همون مجموع حجم فایلهای داخل اونه دیگه خیلی راحت باید بشه حجمش رو فهمید. البته نه با ماشین حساب و جمع زدن دستی. دیدم یه ایدهی خوبی هست که بتونم روش وقت بزارم و چیزای جدید یاد بگیرم نا سلامتی داشتم یه زبان جدید یاد میگرفتم. علی الحساب با ترکیب bash و python یه چیزی سر هم کردم که جواب بده ولی دیدم این دیگه چیز جدیدی نداشت که من یاد بگیرم فوقش در حد تمرین چیزهایی بود که بلد بودم. در نتیجه سعی کردم که همش رو با python بنویسم.
چالش اول این بود که بتونم حجم هر فایل رو پیدا کنم البته با python وگرنه میشه با اجرای یه فایل bash داخل اسکریپت اصلی اینا رو بدست آورد. برای این کار از ماژول os، تابع path و زیر تابع getsize استفاده می کنیم. برای مثال دستور زیر حجم فایل music.mp3 رو در متغیر size ذخیره میکنه:
1 |
size = os.path.getsize("/path/to/music.mp3") |
خب الان باید بتونیم لیست همهی فایلهای موجود در مسیر رو پیدا کنیم که البته کار راحتیه ولی کار وقتی سخت میشه که یادمون میافته که باید حجم پوشههای داخلی رو هم پیدا کنیم. کارهای زیادی برای این مشکل میشه کرد از جمله استفاده از روش بازگشتی ولی خوبه که به اصل سادگی (KISS principle) پایبند باشیم من فقط لازم دارم لیست همهی فایلهای مسیرم رو پیدا کنم تا با دستور بالا بتونم حجمش رو پیدا کنم. البته باید به این نکته توجه کرد که استفادهی صرف از لیست فایلها درست نیست و جواب نمیده (چرا؟ چه سؤال خوبی یادداشت کنید به عنوان تمرین برای جلسهی آینده :) ) پس لازم دارم مسیر کامل فایل رو داشته باشم. برای این کار میتونم دوباره از ماژول os و تابع path استفاده کنم امّا با زیر تابع join به شکل زیر:
1 2 3 |
for dirpath, dirs, files in os.walk(sys.argv[1]): for filename in files: file_list.append(os.path.join(dirpath, filename)) |
خب با این کار یه لیست داریم شامل مسیر کامل همهی فایلهای موجود در پوشهی مورد نظرمون. پس کافیه یکی یکی اینارو بدیم به زیر تابع getsize و جمشون رو جمع بزنیم. :) البته با این کار حجم پوشه برحسب بایت تولید میشه که باید با تقسیم بر ۱۰۲۴ به تعداد مورد نیاز خوندنش رو آسونتر بکنیم. کد نهایی من این شد:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
#!/usr/bin/python3.3 ############################################################# # FileName = dsize.py # # Descriprion = Calcualte a Directory Size and return that. # # FeedBack = Vahid.Maani@gmail.com # ############################################################# # Import Needed Modules import os import sys # Define needed variables file_list = [] size = 0 # Check usage. if len(sys.argv) < 2: print("You should specify a directory like this:") print("\tdir_size.py <directory>") sys.exit() # Fine files list. for dirpath, dirs, files in os.walk(sys.argv[1]): for filename in files: file_list.append(os.path.join(dirpath, filename)) # Find files size and calculate their sum. for x in file_list: size += os.path.getsize(x) unit_list = ["B", "K", "M", "G"] unit = 0 while (size > 1020) and (unit < 4): size /= 1024 unit += 1 print(str(round(size,1))+unit_list[unit]) |
کد رو می تونید در گیتهاب و در این آدرس پیدا کنید.
پی نوشت ۱: توجه داشته باید مقدار حجمی اسکریپت بر میگردونه کاملاً دقیق نیست چون در مرحلهی آخر گرد میشه.
پی نوشت ۲: مقداری که اسکریپت برمیگردونه دقیقتر از مقداری هست که nautilus برای یک پوشه برمیگردونه. دلیلش این هست که ناتیلیوس مقدار حجم هر فایل رو به همراه گرد کردن بدست میاره و با جمع اونها مقدار حجم پوشه رو بدست میاره و بازم گردش می کنه یعنی اگر پوشه دارای زیر پوشهها و فایلهای زیادی باشه تعداد گرد شدن بیشتر میشه و در نتیجه مقدار دقیقی حاصل نمیشه. می تونید امتحان کنید :)
پی نوشت ۳: شاید راههای دیگهای هم برای پیدا کردن حجم یه پوشه باشه ولی خب من خواستم یه راه خودم بسازم و چیزای جدید یاد بگیرم که خب فک کنم موفق شدم :)
خوب جاش از du استفاده میکردی! :دی
همین و بگو :))))
نه آخه میخواستم یه چیزی در مورد برنامه نویسی یاد بگیرم ;)