جستجو فایلها در لینوکس – بخش اول
یک سیستم لینوکس دارای فایلهای زیادی است. این موضوع موجب میشود که این سوال را مطرح کنیم که چگونه هر چیزی را که میخواهیم جستجو کنیم؟
ما میدانیم که سیستم لینوکس بسیار ساختیافته و سازمانیافته است، ولی وجود فایلهای زیاد در این سیستم میتواند برای ما مشکلزا باشد. در نتیجه در این درس و درس بعدی ابزارهایی را معرفی میکنیم که در جستجو فایلهای مختلف در سیستم لینوکس به ما کمک کنند.
فرمان locate – یافتن فایلها به شیوه ساده
فرمان locate جستجوی پایگاهداده مستقیمی را بر روی نام مسیرها انجام میدهد و سپس هر نامی که مطابقت دارد را در خروجی نشان میدهد. برای مثال ما میخواهیم همه برنامههایی که نام آنها با zip شروع میشوند را پیدا کنیم. از آنجایی که ما به دنبال برنامهها میگردیم، فرض میکنیم که نام پوشه حاوی برنامههایی است که به /bin ختم میشوند. در نتیجه میتوانیم با استفاده از locate فایلهای خود را پیدا کنیم:
[me@linuxbox ~]$ locate bin/zip
خروجی (در سیستم ما) چنین خواهد بود:
/usr/bin/zip /usr/bin/zipcloak /usr/bin/zipgrep /usr/bin/zipinfo /usr/bin/zipnote /usr/bin/zipsplit
اگر نیازمندیهای جستجو ساده نبود، میتوانیم locate را با دیگر ابزارها مثل grep نیز ترکیب کنیم تا طراحی جالبتری از جستجوها را پیدا کنیم.
[me@linuxbox ~]$ locate zip | grep bin /bin/bunzip2 /bin/bzip2 /bin/bzip2recover /bin/gunzip /bin/gzip /usr/bin/funzip /usr/bin/gpg-zip /usr/bin/preunzip /usr/bin/prezip /usr/bin/prezip-bin /usr/bin/unzip /usr/bin/unzipsfx /usr/bin/zip /usr/bin/zipcloak /usr/bin/zipgrep /usr/bin/zipinfo /usr/bin/zipnote /usr/bin/zipsplit
برنامه locate سالیان است که در دسترس است و انواع مختلفی از آن وجود دارد. دو مورد از رایجترین آنها در توزیعهای لینوکس slocate و mlocate هستند. هر چند که آنها معمولا از طریق لینک سمبلیک locate در دسترس میباشند. نسخههای مختلف locate دارای گزینههای مشترک زیادی هستند. برخی نسخهها شامل مطابقت عبارات منظم (Regular Expression Matching) و پشتیبانی از وایلدکارها (Wildcard Support) نیز هستند. به منظور تشخیص نسخه نصب شده بر روی توزیع لینوکس خود به صفحات manual مراجعه نمایید.
پایگاهداده locate از کجا میآید؟
حتما متوجه شدهاید که بر روی برخی توزیعهای لینوکس بلافاصله پس از اینکه سیستمعامل نصب شد، فرمان locate کار نمیکند، ولی اگر چند روز بعد امتحان کنید مشکل برطرف شده است. دلیل آن این است که پایگاهداده locate توسط برنامه دیگری با نام updated ایجاد شده است. این برنامه معمولا به صورت دورهای به عنوان cron job اجرا میشود که وظیفهای است که در وهلههای منظم ایجاد میشود. بیشتر سیستمها به صورتی تجهیز شدهاند که فرمان updated را یکبار در روز اجرا کنند. از آنجایی که پایگاهداده به صورت مداوم بروزرسانی نشده است خواهید دید که فایلهای اخیر در هنگام استفاده از locate نشان داده نمیشوند. به منظور چیره شدن بر این مشکل میتوانید فرمان updated را به صورت دستی در خط فرمان اجرا کنید. (به این منظور نیاز به دسترسی کاربر ریشه دارید).
فرمان find – یافتن فایلها از راه دشوار
در حالی که برنامه locate میتواند فایل را منحصرا بر اساس نام آن پیدا کند، فرمان find یک پوشه را (شامل زیرشاخههایش) برای فایلها بر اساس مشخصههای متنوعی جستجو میکند. ما زمان زیادی را صرف کار با فرمان find میکنیم. چرا که ویژگیهای جذاب زیادی دارد که بارها و بارها در درسهای بعدی در حین کار با مفاهیم برنامهنویسی خواهیم دید.
در سادهترین فرم استفاده، فرمان find یک یا چند نام پوشه را به منظور جستجو دریافت میکند. برای مثال میتواند لیستی از پوشه خانگی ما ایجاد کند:
[me@linuxbox ~]$ find ~
در بیشتر حسابهای کاربری فعال، این فرمان یک لیست بلند بالا ایجاد خواهد کرد و از آنجایی که این لیست به خروجی استاندارد فرستاده میشود، میتوانیم آن را به دیگر برنامهها وارد کنیم. مثلا با استفاده از فرمان wc به منظور شمارش فایلها استفاده میکنیم:
[me@linuxbox ~]$ find ~ | wc -l 47068
خیلی تعداد بالاست! زیبایی فرمان find همین است که میتوان آن را برای شناسایی شاخصهای ویژهای استفاده کرد. فرمان find این کار را از طریق اپلیکیشنهای test، actions و options انجام میدهد. در درسهای بعدی به توضیح هر کدام از اینها خواهیم پرداخت.
تستها (Tests)
فرض کنید که لیستی از پوشهها را از جستجوی خود میخواهیم. به این منظور بایستی تست زیر را اضافه کنیم:
[me@linuxbox ~]$ find ~ -type d | wc -l 1695
اضافه کردن –type d جستجوی ما به فقط پوشهها را محدود کرد. در مقابل میتوانیم جستجو را به فایلهای عادی محدود کنیم. به صورت زیر:
[me@linuxbox ~]$ find ~ -type f | wc -l 38737
جدول زیر نوع فایل پشتیبانی شده تستها توسط فرمان find به ما نشان میدهد.
| نوع فایل | توضیحات |
|---|---|
| b | بلوک فایل ویژه دیوایس |
| c | کاراکتر فایل ویژه دیوایس |
| d | پوشه |
| f | فایل عادی |
| l | لینک سمبولیک |
همچنین میتوانیم جستجو را بر اساس اندازه فایل و نام فایل با اضافه کردن تستهای بیشتر انجام دهیم. نگاهی به همه فایلهای عادی که دارای الگوی وایلدکار *.JPG هستند داشته باشید. میبینید که اندازه آنها بزرگتر از ۱ مگابایت است:
[me@linuxbox ~]$ find ~ -type f -name "*.JPG" -size +1M | wc -l 840
در این مثال، ما تست –name را به همراه الگوی فایل JPG وارد کردیم.
توجه کنید که به منظور جلوگیری از بسط نام مسیر آن را در داخل دابل کوتیشن قرار دادیم. سپس تست –size را به همراه اندازه بیشتر از یک مگابایت وارد کردیم. علامت بعلاوه (+) نشاندهنده این است که به دنبالی فایلهایی با اندازه بزرگتر از مقدار ۱مگابایت میگردیم. همانطور که علامت منها (-) را به کار میبردیم به فایلهای کمتر از اندازه ۱ مگابایت اشاره میکردیم. به کار بردن هیچ علامتی قبل از ۱M نشاندهنده این است که به دنبال فایلهایی با اندازه دقیقا ۱Mمیگردیم. M هم همانطور که گفتیم نشاندهنده واحد مگابایت است. واحدهای بیشتر اندازهگیری را در جدول زیر مشاهده میکنید:
| کاراکتر | واحد |
|---|---|
| b | بلوکهای 512 بایتی (بلوک پیشفرض اگر هیچ واحدی تعیین نشده باشد.) |
| c | بایتها |
| w | کلمات دوبایتی |
| k | کیلوبایت |
| M | مگابایت |
| G | گیگابایت |
فرمان find از تعداد زیادی از تستهای مختلف پشتیبانی میکند که شرح همه آنها خارج از حوصله این درس است. جدول زیر موارد رایج را توضیح میدهد. قابل ذکر است مکانهایی که آرگومانهای عددی مورد نیاز است، همان علامتهای بعلاوه (+) و منها (-) که پیشتر توضیح آن را دادیم به کار میروند.
| تست | توضیحات |
|---|---|
| -cmin n | تطبیق فایلها با پوشههایی که محتویات یا مشخصههای آنها دقیقا n دقیقه قبل تغییر یافتهاند. به منظور تعیین کمتر یک n دقیقه از -n استفاده کنید. |
| -cnewer file | مطابقت فایلها با پوشهها که محتویات یا مشخصههای آنها زودتر تغییر یافتهاند. |
| -ctime n | مطابقت فایلها یا پوشههایی که محتوا یا مشخصههای آنها در 24 ساعت اخیر تغییر یافتهاند. |
| -empty | مطابقت فایلها و پوشههای خالی |
| -group name | مطابقت فایل یا پوشههایی که به گروهی با نام name تعلق دارند. name میتواند به عنوان یک نام گروه یا شناسه عددی گروه بیان شود. |
| -iname pattern | درست شبیه تست -name ولی حساس به بزرگی کوچکی حروف نمیباشد. |
| -inum n | مطابقت فایلها با شماره اینود. |
| -mmin n | مطابقت فایلها یا پوشههایی که محتویاتشان n دقیقه قبل اتفاق افتاده است. |
| -mtime n | مطابقت فایلها یا پوشههایی که محتویاتشان فقط 24 ساعت گذشته تغییر یافته است. |
| -name pattern | مطابقت فایلها و پوشهها درون الگوی وایلدکارد تعیین شده |
| -newer file | مطابقت فایلها و پوشههایی که محتویاتشان از فایل تعیین شده زودتر تغییر یافته است. این کار زمانی مفید است که میخواهید اسکریپتهای شل به منظور اجرای بکاپ بنویسید. هر وقت که یک بکاپ ایجاد میکنید، یک فایل را بروز میکنید و سپس از فرمان find استفاده میکنید تا تشخیص دهید کدام فایل از زمان آخرین بروزرسانی تغییر یافته است. |
| -nouser | مطابقت فایل و پوشههایی که به یک کاربر معتبر تعلق ندارند. این کار را میتوان به منظور یافتن فایلهای متعلق به حسابهای کاربری حذف شده و تشخیص فعالیت هکرها انجام داد. |
| -nogroup | مطابقت فایلها و پوشههایی که به یک گروه معتبر تعلق ندارند. |
| -perm mode | مطابقت فایلها یا پوشههایی که مجموعه مجوزهای مربوطه را دارند. mode را میتوان به فرمت اوکتال و یا نشانهگذاری سمبولیک وارد کرد. |
| -samefile name | مشابه تست -inum فایلهایی را که شماره اینود یکسانی را دارند تطبیق میدهد. |
| -size n | مطابقت فایلهایی با اندازه n |
| -type c | مطابقت فایلهای با نوع c |
| -user name | مطابقت فایلها یا پوشههایی که به name تعلق دارند. name ممکن است بوسیله یک نام کاربری یا یک شناسه عددی کاربر وارد شود. |
عملگرها (Operators)
حتی با همه تستهایی که فرمان find برای ما فراهم میکند، ما هنوز نیاز به پیدا کردن یک راه بهتر برای توصیف ارتباط منطقی بین تستها هستیم. برای مثال اگر نیاز داشته باشیم که همه فایلها و زیرشاخههای موجود در یک شاخه را که دارای یک مجوز امن هستند را شناسایی کنیم چه باید کرد.
میخواهیم دنبال همه فایلهایی که مجوز آنها ۰۶۰۰ نیست و پوشههایی که مجوز آنها ۰۷۰۰ نیست بگردیم. مسلما فرمان find یک راهی را برای ترکیب تستها با عملگرهای منطقی به منظور ایجاد روابط منطقی پیچیدهتر فراهم کرده است. به این منظور به مثال زیر توجه کنید:
[me@linuxbox ~]$ find ~ \( -type f -not -perm 0600 \) -or \( -type d -not -perm 0700 \)
به نظر خیلی پیچیده است. ولی واقعا اینطور نیست. اگر که شما مفهوم هر کدام از این عملگرها را بشناسید متوجه میشوید که این عبارت خیلی ساده است. به این منظور جدول زیر را که عملگرهای منطقی فرمان find را توضیح داده مطالعه بفرمایید:
| عملگر | توضیحات |
|---|---|
| -and | مطابقت در صورتیکه تستها در هر دو طرف عملگر صحیح باشند. ممکن است به -a کوتاه شده باشند. |
| -or | مطابقت در صورتی که یک تست از دو طرف عملگر صحیح باشد. |
| -not | مطابقت در صورتیکه تست صحیح نباشد. ممکن است به -! کوتاه شده باشد. |
| ( ) | تستها و عملگرهای گروه برای ایجاد یک عبارت بزرگتر. این یه منظور کنترل اولویت ارزیابیها استفاده میشود. به صورت پیشفرض find از چپ به راست ارزیابی را انجام میدهد. گاها به منظور بدست آوردن نتایج دلخواه لازم است که ترتیب پیشفرض را نادیده بگیریم. حتی در صورتی که لازم نباشد میتوان از آن به منظور قرار دادن گروههای کاراکتری در جهت بهبود خوانایی فرمانها استفاده کرد. |
با در دست داشتن این لیست عملگرها، میتوانیم فرمان find خود را مجددا واسازی کنیم. وقتی که از بالا به فرمان find با ساختار جدید نگاه میکنیم، میبینیم که تستهای ما به دو صورت جداگانه مرتب شدهاند که با یک عملگر –or از هم جدا شدهاند:
(expression 1) -or (expression 2)
تا زمانی که به جستجوی فایلهایی با یک دسته مجوز خاص و پوشههایی با یک دسته مجوز دیگر میگردیم، عبارت بالا کاربردی است.
اگر به دنبال هر دوی فایلها و شاخهها میگردیم، چرا به جای استفاده از –or از –and استفاده نکنیم؟ به این دلیل که زمانی که find فایلها و پوشهها را جستجو میکند، هر کدام ارزیابی را میکند تا ببیند که با تست مورد نظر مطابقت دارد یا نه. ما میخواهیم بدانیم که آیا یک فایل با یک مجوز نادرست است یا یک شاخه با مجوز نادرست است. این نمیتواند هر دو در آن واحد باشد.
پس عبارت خود را به صورت زیر گسترش میدهیم:
(file with bad perms) -or (directory with bad perms)
چالش بعدی ما این است که چگونه مجوزهای نادرست را تست کنیم. در واقع ما چنین کاری نمیکنیم و تنها مجوزهای درست را تست میکنیم. در این مثال فایلها با مجوز درست ۰۶۰۰ تعریف شدهاند. برای شاخهها هم مجوز ۰۷۰۰ تعریف شده است (درواقع برای پیدا کردن مجوزهای نادرست میگوییم آنهایی که درست نیستند مثلا –not perm 600 را پیدا کن).
عبارتی که فایلها را تست میکند به این صورت است:
-type f -and -not -perms 0600
عبارتی که پوشهها را تست میکند به این صورت است:
-type d -and -not -perms 0700
همانطور که در جدول بالا ذکر شده، عملگر –and را میتوان حذف کرد بدون هیچ مشکلی چون که به صورت پیشفرض اعمال خواهد شد.
در نتیجه فرمان را به صورت زیر میتوانیم بنویسیم:
find ~ (-type f -not -perms 0600) -or (-type d -not -perms 0700)
هر چند به دلیل اینکه پرانتزها معنی خاصی در شل (Shell) دارند، بایستی آنها را نادیده بگیریم تا شل آنها را به صورت اشتباه تفسیر نکند. با بکار بردن بکاسلش (\) این کار را انجام دهید.
یک ویژگی دیگر از عملگرهای منطقی وجود دارد که بایستی آن را بفهمیم. فرض کنید که دو عبارت جداگانه با یک عملگر منطقی داریم:
expr1 -operator expr2
در همه موارد عبارت اول اجرا خواهد شد. هر چند که عملگر (-operator) تشخیص خواهد داد عبارت دوم اجرا شود یا نه. جدول زیر نشان میدهد که این عملگرها چگونه کار میکنند:
| نتایج عبارت اول | عملگر | عبارت دوم |
|---|---|---|
| درست باشد | -and | همیشه انجام میشود |
| نادرست باشد | -and | هرگز انجام نمیشود |
| درست باشد | -or | هرگز انجام نمیشود |
| نادرست باشد | -or | همیشه انجام میشود |
چرا اینگونه عمل میکنند؟ به این دلیل که کارایی افزایش یابد. برای مثال –and را در نظر بگیرید. ما میدانیم که در صورتی که نتیجه expr1 نادرست باشد، عبارت expr1 –and expr2 نمیتواند درست باشد. پس در نتیجه هیچ هدفی برای اجرای عبارت expr2 باقی نمیماند و به منظور بهبود عملکرد از اجرای آن ممانعت میشود.
علاوه بر این اگر که عبارت expr1 –or expr2 را داشته باشیم و نتیجه expr1 صحیح باشد، هیچ هدفی برای اجرای expr2 باقی نمیماند. چون که ما از قبل میدانیم که عبارت expr1 –or expr2 صحیح است.
در نتیجه با این کار فرمانها را سریعتر و با عملکرد بهتری انجام میدهیم. در درس بعدی به توضیح Actions خواهیم پرداخت.
درباره فرشید نوتاش حقیقت
همیشه نیازمند یک منبع آموزشی فارسی در حوزه نرمافزارهای آزاد/ متنباز و سیستمعامل گنو/لینوکس بودم. از این رو این رسالت رو برای خودم تعریف کردم تا رسانه «محتوای باز» رو بوجود بیارم.
نوشتههای بیشتر از فرشید نوتاش حقیقتاین سایت از اکیسمت برای کاهش جفنگ استفاده میکند. درباره چگونگی پردازش دادههای دیدگاه خود بیشتر بدانید.
دیدگاهتان را بنویسید