انجمن گروه موج سازان

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

دستور locate یکی از سریع ترین راه های یافتن فایل های مختلف در لینوکس است. ساده ترین نوع استفاده از آن را در زیر مشاهده می کنید:

$ locate filename

یا

$ locate "*.html"

یکی از ضعف های این دستور، عدم جستجو در فایل سیستم های مانت شده ویندوز است. به عبارت دیگر این دستور به صورت پیش فرض پارتیشن ویندوزی من را برای یافتن فایل جستجو نمی کند.
در صورت زیاد بودن نتایج جستجو، از پارامتر n دستور locate برای ایجاد محدودیت استفاده نمایید:

$ locate "*.php" -n 10

و نیز می توانید نتایج را با دستورات less یا more ترکیب کنید:

$ locate "*.php" | more

نکته: در هنگام استفاده از locate برای نخستین بار ممکن است با پیغام خطای مروبوط به عدم وجود پایگاه داده مواجه شوید. برای رفع این مشکل از دستور زیر برای بروز کردن پایگاه داده استفاده نمایید:

$ sudo updatedb

۲- دستور find

find یکی از انعطاف پذیرترین و قوی ترین دستورات برای جستجوی فایل هاست. در زیر ساده ترین ساختار استفاده از دستور find آمده است:

$ find / -name 'index.php'

دستور بالا تمامی فایل های index.php موجود در پارتیشن ریشه (/) و زیر شاخه های آن را نمایش می دهد.
درصورتی که به خطای اجازه دسترسی در جستجو برخورد کردید، با اضافه کردن ۲>/dev/null آن را نادیده بگیرید. همچنین می توانید با اضافه کردن ۲>errors.txt آن خطا ها را در فایل errors.txt ذخیره نمایید:
$ find / -name 'index.php' 2>/dev/null
$ find / -name 'index.php' 2>errors.txt
در ادامه برخی از کاربرد های دستور find را بررسی می کنیم.
$ find /home/saeid -name 'index*'
$ find /home/saeid -iname 'index*'
دستور اول در بالا تمامی فایل هایی را که با عبارت index شروع شده و در دایرکتوری /home/saeid هستند را نمایش می دهد.
دستور دوم، عملکردی مشابه با دستور اول دارد، با این تفاوت در این دستور اندازه حروف (بزرگی و کوچکی) آنها در نظر گرفته نمی شود. یعنی فایل هایی مانند InDex.php یا iNDEX نیز در نتایج دیده می شوند.
$ find -name s*
دستور بالا تمامی فایل ها و دایکتوری هایی را که با حرف s شروع شده و در دایکتوری جاری می باشند را نمایش می دهد.

$ find /home/saeid/Music -name '*.mp3' -size -5000k
$ find / -size +10000k

دستور اول تمامی فایل های mp3 موجود در دایکتوری /home/saeid/Music که کمتر از ۵۰۰۰ کیلوبایت حجم دارند را نمایش می دهد.
دستور دوم تمامی فایل هایی را که بیش از ۱۰۰۰۰ کیلوبایت حجم دارند را نمایش می دهد.
$ find /home/saeid -amin -10 -name '*.php'
$ find /home/saeid -atime -2 -name '*.php'
$ find /home/saeid -mmin -10 -name '*.php'
$ find /home/saeid -mtime -2 -name '*.php'
دستور اول تمامی فایل های php موجود در پوشه خانگی کاربر saeid و زیر شاخه های آن را که در ۱۰ دقیقه اخیر مورد دسترسی قرار گرفته اند را نمایش می دهد.
دستور دوم عملکردی مشابه با دستور اول دارد، با این تفاوت که فایل های مورد دسترسی در ۲ ساعت اخیر را نمایش می دهد.
دستور سوم و چهار عملکردی مشابه با دستور اول و دوم دارند، با این تفاوت که فایل هایی را که در محتوای آنها تغییراتی صورت گرفته است را نمایش می دهند.
$ find / -mount -name 'win*'
دستور بالا تمامی فایل هایی را که با عبارت win شروع شده و در دایرکتوری / بوده و توسط فایل سیستمی مانت (mount) نشده باشند را نمایش می دهد. این دستور زمانی کاربردی تر است که پارتیشن های ویندوزی شما به صورت پیش فرض مانت می شوند و عبارت مورد جستجو (مانند عبارت win) نتایج بسیاری در این پارتیشن ها داشته باشد.
$ find /home/saeid/Music -name 'Metallica*' -and -size +10000k
$ find /home/saeid/Music -size +10000k ! -name "Metallica*"
$ find /home/saeid/Music -name 'Metallica*' -or -size +10000k

عملکرد های شرطی and و or و not دستور find را بسیار انعطاف پذیر می کنند. به عنوان مثال دستور دوم تمامی فایل هایی را که بیش از ۱۰۰۰۰ کیلو بایت حجم داشته و نام آن ها با عبارت Metallica شروع نشده باشد را نمایش می دهد.

گزینه exec یکی از مهمترین ویژگی های دستور find است. با استفاده از این گزینه شما می توانید دستوری را بر روی نتایج جستجو اعمال کنید. نمونه ساده استفاده از این دستور را در زیر مشاهده می کنید:
$ find / - name 'Metallica*' -exec ls -lh {} \;
دستور بالا یک لیست (ls -lh) با جزییات از نتایج جستجو را نمایش می دهد.
۳- دستور whereis

این دستور برای جستجو فایل های اجرایی، منبع و راهنمای یک دستور مورد استفاده قرار می گیرد:
$ wheris nano
۴- دستور which

دستور which برای بدست آوردن آدرس کامل دستور اجرایی مورد استفاده قرار می گیرد. به عنوان مثال خروجی دستور زیر عبارت /usr/bin/nano است.
$ which nano

موفق باشید

منبع
برای پیدا کردن یک عبارت در داخل یک فایل از دستور grep -r yoursen

میتوانید استفاده کنید

مثلا

grep -r root /etc/passwd
یکی از option های find که کاربرد بسیاری دارد -type است که مانند مثال استفاده می شود
find -type d -name "filename"
مثال بالا فقط به دنبال دایرکتوری ها میگردد

option دیگر -maxdepth است که میتوانید تا به تعداد مرحله که بهش میدید داخل دایکتوری ها برود مانند مثال
find -maxdepth 1 -name "filename"
مثال بالا فقط دایرکتوری جاری را میگردد
یکی دیگر از option های خیلی خوب find
جست و جو در permission ها
find -perm -u=s
مثال بالا تمامی فایل هایی که suid انها set شده است را میابد
می توان به جای u (یوزر) از g (گروه) یا o (اودر)other> استفاده کرد و s به معنای suid میباشد که میتواند x (اجرایی) یا ... باشد
find -perm 777
مثال بالا تمامی فایل هایی که permission انها 777 است را نمایش میدهد
دستور find یکی از شگفت انگیز ترین دستورات لینوکس است. با این دستور میتوانید کارهای بسیار جالبی انجام دهید. این دستور برای پیدا کردن فایلی در یک شاخه خاص و تمام زیرشاخه های آن استفاده میشود. جستجوها میتواند بسیار متنوع باشد و امکانات برنامه بسیار مفصل است.

ابتدا دستور زیر را در ترمینال خود بزنید ( برای باز کردن ترمینال در محیط گنوم، به منوی Applications رفته و سپس به زیرمنوی Accessories بروید و در آخر Terminal را انتخاب کنید)

اگر دستور find را بدون هیچ آرگومان و گزینه ای وارد کنید، لیست تمام فایلهای موجود در شاخه جاری و زیر شاخه‌های آن را چاپ میکند. می‌توانید بلافاصله پس از دستور مسیری را که میخواهید جستجو در آنجا انجام شود را وارد کنید مثال زیر جستجو را در دایرکتوری /etc انجام میدهد و تمام فایلهای موجود در آن شاخه و زیرشاخه هایش را نمایش میدهد.

کد: [/url]انتخاب همه[co دایرکتوری خانگی کاربر پیدا میکند. (فایلهای مخفی فایلهایی هستند که با یک نقطه در ابتدای نامشان شروع شوند.)

کد:
انتخاب همه
کد:
$ find  /home/$USERNAME  -iname  .\*


۱۰- جستجو بر اساس حجم فایل

یکی دیگر از گزینه های مفید find گزینه size- است. این گزینه فایلها را بر اساس حجم جستجو میکند. به دستور زیر توجه کنید:
کد: انتخاب همه
کد:
$ seq 1000000 > file1
$ ls -lh file1
-rw-r--r-- 1 javad javad 6.6M Sep 22 21:56 file1
$ find -size +5M
./file1


در دستور اول یک فایل با محتویات ۱ تا ۱۰۰۰۰۰۰ ایجاد کردیم. در دستور دوم مشاهده میکنید که حجم فایل 6.6 مگابایت است. گزینه -h در دستور ls حجم را به صورت قابل درک برای انسان نمایش میدهد و مخفف –human-redeable است. دستور سوم فایلهای بزرگ‌تر از 5 مگابایت را نشان میدهد. علامت + به معنای بزرگ‌تر ، علامت – به معنای کوچکتر و بدون علامت به معنای این است که حجم فایل دقیقاً همان مقدار مشخص شده باشد. همچنین M به معنای مگابایت است. بقیه واحد ها را ببینید:

b به معنی بایت است (این گزینه پیشفرض است)
c به معنی بایت است
w به معنی دوبایت کلمه است
k به معنی کیلو بایت است
M به معنی مگابایت است
G به معنی گیگابایت است

برای مثال دستور زیر فایلهایی را که بیشتر از ۱۰۰ کیلو بایت و کمتر از یک مگابایت حجم دارند را نشان میدهد:

کد: انتخاب همه
کد:
$ find . -size +100k -and -size -1M


نکته: یادتان باشد بیشتر آرگومانهای عددی میتوانند به صورت زیر مشخص شوند:
+n یعنی فایلهای بزرگ‌تر از n
-n یهنی فایلهای کوچکتر از n
n یعنی دقیقاً برابر با n

پیدا کردن فایل‌ها بر اساس تاریخ

هر فایلی ۳ نوع تاریخ دارد.

Access time: تاریخ آخرین باری که یک برنامه یا یک کاربر از فایل استفاده کرده.
Modification time: تاریخ آخرین باری که محتویات یک فایل تغییر کرده مثلاً یک خط به آن فایل اضافه شده.
Change time: تاریخ آخرین باری که اطلاعات inode آن فایل تغییر کرده مثلاً وقتی مجوز یک فایل عوض شود این تاریخ بروز می شود.

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

آرگومان min: به عنوان دقیقه تفسیر می‌شود مثلاً min 40 یعنی دقیقاً 40 دقیقه پیش. یا min +40 یعنی بیشتر از ۴۰ دقیقه بیش وmin -40 یعنی در ۴۰ دقیقه اخیر.

آرگومان time: به عنوان روز یعنی ۲۴ ساعت تفسیر میشود. برای مثال time 2 یعنی 2*24 ساعت پیش

در حالت time، قسمتهای کوچک‌تر در نظر گرفته نمیشوند برای مثال ۲۵ ساعت، به ۲۴ ساعت تبدیل می‌شود و همچنین ۴۷ ساعت هم به عنوان ۲۴ ساعت
تفسیر میشود. ۴۸ ساعت تا ۷۱ به عنوان ۴۸ ساعت در نظر گرفته می‌شوند و الی آخر.

برای پیدا کردن فایل بر اساس تاریخ تغییر محتویات آن (Modification time) از گزینه های -mmin و -mtime استفاده میشود.

-mmin n یعنی محتویات فایل در n دقیقه پیش تغییر کرده.
-mtime n یعنی محتویات فایل در n*24 ساعت پیش تغییر کرده است.

مثال زیر دایرکتوری جاری و تمام زیر دایرکتوری هایش را جستجو میکند و فایلهایی را نشان میدهد که محتویات آن‌ها در ۶۰ دقیقه اخیر تغییر کرده‌ است

کد: انتخاب همه
کد:
$ find . -mmin -60


مثال زیر هم دایرکتوری ریشه یعنی / را جستجو میکند و فایلهایی را که محتویات آن‌ها در ۲۴ ساعت گذشته یا یک روز پیش تغییر کرده‌ است را نشان میدهد.

کد: انتخاب همه
کد:
$ find / -mtime -1


برای جستجوی فایل‌ها بر اساس تاریخ آخرین دسترسی از دو گزینه -amin و -atime استفاده میکنیم.

-amin n فایل‌هایی که در n دقیقه پیش، توسط کاربر یا برنامه‌ای در دسترس قرار گرفته اند.
-atime n فایل‌هایی که در n*24 ساعت پیش، توسط کاربر یا برنامه‌ای در دسترس قرار گرفته اند.

مثال زیر دایرکتوری جاری و تمام زیر دایرکتوری ها را برای فایلهایی که «دقیقا» ۲۰ دقیقه پیش در دسترس قرار گرفته را نشان میدهد.

کد: انتخاب همه
کد:
$ find . -amin 20


مثال زیر هم دایرکتوری ریشه یعنی / را جستجو میکند و فایلهایی را که محتویات آن‌ها «دقیقا» در ۲۴ ساعت گذشته یا یک روز پیش در دسترس قرار گرفته را نشان میدهد.

کد: [url=http://forums.technotux.org/viewtopic.php?f=1&t=21052#]انتخاب همه
کد:
$ find . -atime 1


برای جستجوی فایل‌ها بر اساس تاریخ تغییر inode number آن‌ها از دو گزینه -cm به نام list ذخیره میکند. اگر این فایل وجود نداشته باشد ساخته می‌شود و اگر وجود داشته باشد بر روی آن overwrite میشود.

-print
این گزینه باعث می‌شود که خروجی در (standard output) چاپ شود. البته بعد از هر فایل یک کاراکتر newline قرار میدهد تا هر فایل در یک سطر قرار گیرد. اگر خروجی find را به برنامه‌ای لوله بندی میکنید و در نام فایل کاراکتر newline وجود دارد، از -print0 استفاده کنید فایلها پشت سر هم قرار گیرند. این گزینه پیش‌فرض است.

-print0
نام کامل فایلها را در خروجی چاپ میکند و بین هر فایل یک کاراکتر null قرار میدهد (در عوض newline). با این کار اگر در نام فایل کاراکتر newline یا نوع دیگری از white space وجود داشته باشد، توسط برنامه‌هایی که خروجی find را میخوانند به درستی تفسیر شوند. همچنین معادل گزینه -0 در فرمان xargs است.

-fprint0
همانند -print0 فقط خروجی را به جای صفحه نمایش به یک فایل میفرستد. اگر فایل وجود نداشته باشد ایجاد و در صورت وجود overwrite میشود.

-fprint
همانند -print ولی خروجی رابه جای صفحه نمایش به یک فایل میفرستد. اگر فایل
دستور find یکی از شگفت انگیز ترین دستورات لینوکس است. با این دستور میتوانید کارهای بسیار جالبی انجام دهید. این دستور برای پیدا کردن فایلی در یک شاخه خاص و تمام زیرشاخه های آن استفاده میشود. جستجوها میتواند بسیار متنوع باشد و امکانات برنامه بسیار مفصل است.

ابتدا دستور زیر را در ترمینال خود بزنید ( برای باز کردن ترمینال در محیط گنوم، به منوی Applications رفته و سپس به زیرمنوی Accessories بروید و در آخر Terminal را انتخاب کنید)

اگر دستور find را بدون هیچ آرگومان و گزینه ای وارد کنید، لیست تمام فایلهای موجود در شاخه جاری و زیر شاخه‌های آن را چاپ میکند. می‌توانید بلافاصله پس از دستور مسیری را که میخواهید جستجو در آنجا انجام شود را وارد کنید مثال زیر جستجو را در دایرکتوری /etc انجام میدهد و تمام فایلهای موجود در آن شاخه و زیرشاخه هایش را نمایش میدهد.

کد: انتخاب همه
$ find /etc



در مثال بالا از مسیر کامل (Absolute Path) استفاده کردیم. به جای نوشتن مسیر کامل میتوانید از مسیر نسبی هم استفاده کنید و یا اصلاً مسیری را ننویسید که در این صورت پوشه جاری استفاده خواهد شد. توجه داشته باشید که اگر از مسیر کامل استفاده کنیم، find هم آدرس فایلها را با مسیر کامل به ما میدهد و اگر از مسیر نسبی استفاده کنیم، find به ما مسیر نسبی فایلها را میدهد. به دو مثال زیر توجه کنید.

کد: انتخاب همه
$ find /etc
/etc/apache2/mods-available/suexec.load
/etc/apache2/mods-available/alias.load
/etc/apache2/mods-available/ext_filter.load
/etc/apache2/magic
/etc/networks
..

$ find .
./apache2/mods-available/suexec.load
./apache2/mods-available/alias.load
./apache2/mods-available/ext_filter.load
./apache2/magic
./networks



پیدا کردن فایلها بر اساس نام:
این کار ساده‌ترین روش استفاده از find است. نام فایل را بعد از گزینه -name وارد کنید. دستور زیر تمام فایلهایی را که MyCProgram.c نام دارد را درشاخه جاری و تمام زیر شاخه هایش جستجو کرده و نتیجه را نمایش میدهد.

کد: انتخاب همه
$ find -name "MyCProgram.c"
./backup/MyCProgram.c
./MyCProgram.c


گزینه -name به حروف کوچک و بزرگ حساس است. مثلاً در مثال بالا فایل mycprogram.c را پیدا نمیکند. اگر میخواهید عبارت حساس به حروف کوچک و بزرگ نباشد، به جای -name از -iname استفاده کنید که مخفف insensitive name است.

کد: انتخاب همه
$ find -iname "MyCProgram.c"
./mycprogram.c
./backup/mycprogram.c
./backup/MyCProgram.c
./MyCProgram.c



مشخص کردن نوع فایل
این امکان وجود دارد که به دستور find بگویید فقط نوع خاصی از فایلها را جستجو کند. مثلاً فقط دایرکتوری ها را جستجو کند و با فایلهای معمولی کاری نداشته باشد. این کار با گزینه -type انجام میشود. به مثال زیر توجه کنید:

کد: انتخاب همه
$ find -type f
./MybashProgram.sh
./create_sample_files.sh
./backup/MybashProgram.sh
..



در دستور بالا به find گفتیم فقط فایل‌هایی را چاپ کن که از نوع f یا فایل معمولی باشند.در زیر لیست کامل آرگومانهای گزینه type آمده است:

f فایل معمولی
b (block device)
c character device
d دایرکتوری
D door برای سیستم عامل سولاریس
p پایپ (pipe)
s سوکت
l لینک نرم این حرف L است نه یک


میتوانیم با گزینه های mindepth و maxdepth عمق جستجو را مشخص کنیم. مثلاً از زیر دایرکتوری دوم به پایینتر جستجو نکند و یا حتی برای مثال از زیر دایرکتوری سوم شروع به جستجو کرده و تا زیر دایرکتوری پنجم جستجو کند.دستور زیر فایلی به نام passwd را در مسیر / با عمق یک زیر دایرکتوری جستجو میکند. ( یعنی ریشه level اول و یک شاخه پایینتر level دوم)

کد: انتخاب همه
$ find / -maxdepth 2 -name passwd
./etc/passwd



دستور زیر هم مشابه دستور بالاست. فقط جستجو را با دو زیر شاخه انجام میدهد (جمعا ۳ زیر شاخه)

کد: انتخاب همه
$ find / -maxdepth 3 -name passwd
./usr/bin/passwd
./etc/pam.d/passwd
./etc/passwd



دستور زیر با دو دستور بالا کمی تفاوت دارد. این دستور جستجو را از زیر شاخه دوم تا زیر شاخه چهارم انجام میدهد. گزینه -mindepth مشخص میکند که جستجو از کدام زیر شاخه آغاز شود.

کد: انتخاب همه
$ find / -mindepth 3 -maxdepth 5 -name passwd
./usr/bin/passwd
./etc/pam.d/passwd



هر فایل در لینوکس دارای inode است. اطلاعاتی مانند مجوز ها، تاریخ ، مالک
و … در آن ذخیره می‌شود و با استفاده از آن میتوان فایل را شناسایی کرد. Inode را میتوانید مانند شناس‌نامه برای انسان در نظر بگیرید. هر inode یک شماره دارد که با آن شماره مشخص می‌شود و به آن inode-number میگویند. Inode-number را میتوانید مانند شماره شناس‌نامه فرض کنید. این شماره برای هر فایل یکتاست. میتوانید با گزینه ls -i شماره inode هر فایل را ببینید.

کد: انتخاب همه
$ ls -1i
2031811 backup
991235 create_sample_files.sh
991233 MybashProgram.sh
991236 mYcpROgram.c



این دستورات را امتحان کنید:

کد: انتخاب همه
$ touch 'test-file-name'
$ touch 'test-file-name '
$ ls -1 test*
test-file-name
test-file-name



دقت کنید که فایل دوم یک space در انتهای نام خود دارد. خروجی دستور ls به ما درست نشان نمیدهد که کدام فایل در پایان نامش space دارد. در ضمن هر inode number میتواند چند نام داشته باشد که به این نامها لینک سخت میگویند. اگر شماره inode فایل را بدانید میتوانید تمام لینکهای سخت مربوط به آن فایل را با find پیدا کنید.

کد: انتخاب همه
$ ln create_sample_files.sh create_file.sh
$ ls -li
991235 -rwxr-xr-x 2 javad javad 177 Sep 22 18:59 create_file.sh
991235 -rwxr-xr-x 2 javad javad 177 Sep 22 18:59 create_sample_files.sh


در ابتدا با دستور ln یک لینک سخت به فایل create_sample_files.sh با نامcreate_file.sh ایجاد کردیم. در خروجی دستور دوم، ستون اول شماره i-node را
نشان میدهد که برای هر دو فایل مساوی است و در ستون سوم تعدا لینکها را میبینید که مقدار ۲ است.

حالا برای جستجوی تمام لینک های سخت مربوط به inode number 991235 از دستور find به شکل زیر استفاده میکنیم:

کد: انتخاب همه
$ find -inum 991235
./create_file.sh
./create_sample_files.sh



عملگر های -and -not و -or

دستور find اجازه استفاده از عملگر های -and -not و -or را به ما میدهد. عملگر -not نتیجه را برعکس میکند. به مثال زیر توجه کنید:

کد: انتخاب همه
$ find -maxdepth 1 -not -iname "MyCProgram.c"
.
./MybashProgram.sh
./create_sample_files.sh
./backup
./Program.c


دستور بالا با عمق یک دایرکتوری تمام فایلهایی را که نام آن‌ها Myprogram.c (غیر حساس به حروف کوچک و بزرگ) نیست را پیدا کرده و چاپ میکند.
میتوانید به جای -not از ! هم استفاده کنید. در این صورت باید قبل از ! یک بک اسلش (\) قرار دهید تا shell (پوسته)این علامت را به اشتباه تفسیر نکند. دستور زیر مشابه دستور بالاست.

کد: انتخاب همه
$ find -maxdepth 1 \! -iname "MyCProgram.c"




عملگر -and یا -a دو شرط را با هم ترکیب میکند. مثلاً میتوان مشخص کرد فایلهایی را که Program.c نام دارند «و» از نوع f یا فایل معمولی هستند. البته شما همیشه مجبور به استفاده از آن نیستید و مثلاً دستورات زیر یکی هستند:

کد: انتخاب همه
$ find -type f -iname Program.c
$ find -type f -and -iname Program.c
./backup/program.c
./Program.c



مثال بالا فایلهایی را که نامشان program.c (غیر حساس به کوچک و بزرگی حروف) و از نوع فایل معمولی هستند را چاپ کرد. گزینه -a مخفف -and است.


گزینه -or به معنی «یا» است. مثلاً میگوییم فایلهایی را پیدا کن که 10M «یا» +10M حجم دارند. از -and نمیتوان استفاده کرد، چون هیچ فایلی نیست که دقیقاً ۱۰ مگابایت و بیشتر حجم داشته باشد!

کد: انتخاب همه
$ find . -size 10M -or +10M




نکته : تفاوت عملگرهای -and و -not و -or با معادل کوچکتر شده شان این است که این‌ها با استاندارد POSIX منطبق نیستند در حالی که عملگر های ! و -o
و -a با این استاندارد منطبقند.

جستجو بر اساس مجوز فایل

برای جستجو بر اساس مجوزهای یک فایل سه حالت پیش می آید:

۱- فایلی که دقیقاً دارای مجوز خاصی باشد، یعنی صریحاً مجوز فایل را اعلام کنیم مثل ۷۷۷ یا ۶۴۴
۲- چک کردن اینکه آیا فایلی یک مجوز خاص را دارد یا نه. مثلاً فایلی را جستجو کنیم که فقط دارای مجوز اجرا باشد و دیگر کاری نداشته باشیم که آیا آن فایل مجوز نوشتن و … را دارد یا نه.
۳- جستجو با دادن اعداد در مبنای ۸

فرض کنید که دایرکتوری با این فایلها داریم. توجه کنید که مجوز این فایلها با هم متفاوت است.

کد: انتخاب همه
$ ls -l
total 0
-rwxrwxrwx 1 root root 0 2009-02-19 20:31 all_for_all
-rw-r--r-- 1 root root 0 2009-02-19 20:30 everybody_read
---------- 1 root root 0 2009-02-19 20:31 no_for_all
-rw------- 1 root root 0 2009-02-19 20:29 ordinary_file
-rw-r----- 1 root root 0 2009-02-19 20:27 others_can_also_read
----r----- 1 root root 0 2009-02-19 20:27 others_can_only_read



حالا میخواهیم تمام فایلهایی که گروه آن‌ها مجوز خواندن را دارد را پیدا کنیم. این کار بدون توجه به دیگر مجوزها انجام می‌شود. در این مثال برای ما فقط مهم
این است که گروه مجوز خواندن داشته باشد .

کد: انتخاب همه
$ find . -perm -g=r -type f -exec ls -l {} \;
----r----- 1 javad javad 0 Sep 22 21:24 ./others_can_only_read
-rwxrwxrwx 1 javad javad 0 Sep 22 21:24 ./all_for_all
-rw-r--r-- 1 javad javad 0 Sep 22 21:24 ./everybody_read
-rw-r----- 1 javad javad 0 Sep 22 21:24 ./others_can_also_read



در مثال زیر find فایلهایی را پیدا میکند که « فقط » مجوز خواندن برای گروه را دارند. فرق آن با مثال بالا در این است که فایل مورد نظر ما به جز مجوز خواندن
برای گروه مجوز دیگری نداشته باشد.

کد: انتخاب همه
$ find . -perm g=r -type f -exec ls -l {} \;
----r----- 1 root root 0 2009-02-19 20:27 ./others_can_only_read


مثال زیر دقیقاً همان مثال بالاست با این تفاوت که جستجو در مبنای ۸ انجام می شود.

کد: انتخاب همه
$ find . -perm 040 -type f -exec ls -l {} \;
----r----- 1 root root 0 2009-02-19 20:27 ./others_can_only_read



گزینه -empty جستجو را برای فایلهایی انجام میدهد که خالی هستند. این فایلها معمولاً توسط برنامه‌های کاربردی ساخته میشوند.

کد: انتخاب همه
$ find ~ -empty



دستور زیر مشابه دستور بالاست با این تفاوت که زیر دایرکتوری ها را جستجو نمیکند و به جستجو در پوشه جاری بسنده میکند.

کد: انتخاب همه
$ find . -maxdepth 1 -empty



۹- wildcard ها
همانطور که گفته شد برای جستجو بر اساس نام باید از -name و برای غیر حساس بودن به کوچک و بزرگی حروف از -iname استفاده کنیم. ولی این دو گزینه فقط فایلهایی را نشان میدهند که نام آن‌ها دقیقاً شامل کاراکتر های مشخص شده در فرمان باشد. مثلاً فرمان زیر فقط فایل Program.c را نشان میدهد و دیگر فایل MyCProgram.c نشان داده نمی‌شود چون در ابتدای نامش چند کاراکتر اضافه وجود دارد.

کد: انتخاب همه
$ find -name Program.c



برای حل این مشکل باید از wildcard ها استفاده کنیم.

کد: انتخاب همه
$ find -name \*Program.c



از کاراکتر \ بک اسلش برای این استفاده کردیم که شل کاراکتر * را به اشتباه تفسیر نکند بلکه آن را به عنوان یک آرگومان به دستور find بفرستد.

دستور زیر تمام فایلهای مخفی را در دایرکتوری خانگی کاربر پیدا میکند. (فایلهای مخفی فایلهایی هستند که با یک نقطه در ابتدای نامشان شروع شوند.)

کد: انتخاب همه
$ find /home/$USERNAME -iname .\*



۱۰- جستجو بر اساس حجم فایل

یکی دیگر از گزینه های مفید find گزینه size- است. این گزینه فایلها را بر اساس حجم جستجو میکند. به دستور زیر توجه کنید:

کد: انتخاب همه
$ seq 1000000 > file1
$ ls -lh file1
-rw-r--r-- 1 javad javad 6.6M Sep 22 21:56 file1
$ find -size +5M
./file1



در دستور اول یک فایل با محتویات ۱ تا ۱۰۰۰۰۰۰ ایجاد کردیم. در دستور دوم مشاهده میکنید که حجم فایل 6.6 مگابایت است. گزینه -h در دستور ls حجم را به صورت قابل درک برای انسان نمایش میدهد و مخفف –human-redeable است. دستور سوم فایلهای بزرگ‌تر از 5 مگابایت را نشان میدهد. علامت + به معنای بزرگ‌تر ، علامت – به معنای کوچکتر و بدون علامت به معنای این است که حجم فایل دقیقاً همان مقدار مشخص شده باشد. همچنین M به معنای مگابایت است. بقیه واحد ها را ببینید:

b به معنی بایت است (این گزینه پیشفرض است)
c به معنی بایت است
w به معنی دوبایت کلمه است
k به معنی کیلو بایت است
M به معنی مگابایت است
G به معنی گیگابایت است

برای مثال دستور زیر فایلهایی را که بیشتر از ۱۰۰ کیلو بایت و کمتر از یک مگابایت حجم دارند را نشان میدهد:

کد: انتخاب همه
$ find . -size +100k -and -size -1M



نکته: یادتان باشد بیشتر آرگومانهای عددی میتوانند به صورت زیر مشخص شوند:
+n یعنی فایلهای بزرگ‌تر از n
-n یهنی فایلهای کوچکتر از n
n یعنی دقیقاً برابر با n

پیدا کردن فایل‌ها بر اساس تاریخ

هر فایلی ۳ نوع تاریخ دارد.

Access time: تاریخ آخرین باری که یک برنامه یا یک کاربر از فایل استفاده کرده.
Modification time: تاریخ آخرین باری که محتویات یک فایل تغییر کرده مثلاً یک خط به آن فایل اضافه شده.
Change time: تاریخ آخرین باری که اطلاعات inode آن فایل تغییر کرده مثلاً وقتی مجوز یک فایل عوض شود این تاریخ بروز می شود.

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

آرگومان min: به عنوان دقیقه تفسیر می‌شود مثلاً min 40 یعنی دقیقاً 40 دقیقه پیش. یا min +40 یعنی بیشتر از ۴۰ دقیقه بیش وmin -40 یعنی در ۴۰ دقیقه اخیر.

آرگومان time: به عنوان روز یعنی ۲۴ ساعت تفسیر میشود. برای مثال time 2 یعنی 2*24 ساعت پیش

در حالت time، قسمتهای کوچک‌تر در نظر گرفته نمیشوند برای مثال ۲۵ ساعت، به ۲۴ ساعت تبدیل می‌شود و همچنین ۴۷ ساعت هم به عنوان ۲۴ ساعت
تفسیر میشود. ۴۸ ساعت تا ۷۱ به عنوان ۴۸ ساعت در نظر گرفته می‌شوند و الی آخر.

برای پیدا کردن فایل بر اساس تاریخ تغییر محتویات آن (Modification time) از گزینه های -mmin و -mtime استفاده میشود.

-mmin n یعنی محتویات فایل در n دقیقه پیش تغییر کرده.
-mtime n یعنی محتویات فایل در n*24 ساعت پیش تغییر کرده است.

مثال زیر دایرکتوری جاری و تمام زیر دایرکتوری هایش را جستجو میکند و فایلهایی را نشان میدهد که محتویات آن‌ها در ۶۰ دقیقه اخیر تغییر کرده‌ است

کد: انتخاب همه
$ find . -mmin -60



مثال زیر هم دایرکتوری ریشه یعنی / را جستجو میکند و فایلهایی را که محتویات آن‌ها در ۲۴ ساعت گذشته یا یک روز پیش تغییر کرده‌ است را نشان میدهد.

کد: انتخاب همه
$ find / -mtime -1



برای جستجوی فایل‌ها بر اساس تاریخ آخرین دسترسی از دو گزینه -amin و -atime استفاده میکنیم.

-amin n فایل‌هایی که در n دقیقه پیش، توسط کاربر یا برنامه‌ای در دسترس قرار گرفته اند.
-atime n فایل‌هایی که در n*24 ساعت پیش، توسط کاربر یا برنامه‌ای در دسترس قرار گرفته اند.

مثال زیر دایرکتوری جاری و تمام زیر دایرکتوری ها را برای فایلهایی که «دقیقا» ۲۰ دقیقه پیش در دسترس قرار گرفته را نشان میدهد.

کد: انتخاب همه
$ find . -amin 20



مثال زیر هم دایرکتوری ریشه یعنی / را جستجو میکند و فایلهایی را که محتویات آن‌ها «دقیقا» در ۲۴ ساعت گذشته یا یک روز پیش در دسترس قرار گرفته را نشان میدهد.

کد: انتخاب همه
$ find . -atime 1



برای جستجوی فایل‌ها بر اساس تاریخ تغییر inode number آن‌ها از دو گزینه -cmin و -ctime استفاده میکنیم.

مثال زیر دایرکتوری جاری و تمام زیر دایرکتوری ها را برای فایلهایی که inode آن‌ها در «بیشتر» از ۲۰ دقیقه پیش تغییر کرده را نشان میدهد.

کد: انتخاب همه
$ find . -cmin +60



مثال زیر دایرکتوری ریشه و تمام زیر دایرکتوری هایش را برای فایلهایی که inode آن‌ها در «بیشتر» از ۲۴ ساعت یا یک روز پیش تغییر کرده را نشان میدهد.

کد: انتخاب همه
$ find / -ctime +1



همه دستورات بالا دایرکتوری ها را هم نشان میدهند به خاطر اینکه وقتی یک فایل توسط برنامه‌ یا کاربری دسترسی پیدا کرد، دایرکتوری که فایل مورد نظر در آن قرار دارد هم تغییر میکند بنابراین بهتر است جستجو را با -type f محدود به فایلها کنید.

پیدا کردن فایلی از طریق مقایسه آن با Modification time فایلی دیگر فرض کنید که یک ساعت پیش فایل MybashProgram.sh را ویرایش کردید. حالا میخواهید تمام فایلهایی که از آن موقع تا کنون تغییر کرده‌اند را ببینید. گزینه -newer این کار را انجام میدهد و فایلهایی را که Modification time آن‌ها از یک فایل خاص جدیدتر است را نمایش میدهد. مسیر کامل این فایل خاص را باید بعد از -newer وارد کنید.

کد: انتخاب همه
$ find -newer MybashProgram.sh
./file1
./test2
./test2/others_can_only_read
./test2/ordinary_file



-anewer
مثال زیر فایل‌هایی که بعد از ویرایش فایل /etc/hosts در دسترس قرار گرفته‌اند را نشان میدهد. اگر شما به خاطر می آورید که چیزی را به فایل /etc/hosts اضافه کردید و میخواهید فهرست تمام فایل‌هایی را ببینید که بعد از آن در دسترس قرار گرفته‌اند این دستور را بزنید.

کد: انتخاب همه
$ find -anewer /etc/hosts



-cnewer
مثال زیر تمام فایلهایی را نشان میدهد که inode آن‌ها پس از ویرایش محتویات فایل /etc/fstab ، تغییر کرده . اگر شما یادتان می‌آید که یک mount point به فایل /etc/fstab اضلفه کرده‌اید و میخواهید تمام فایلهایی را که پس از آن واقعه ، اطلاعات inode شان تغییر کرده را ببینید این دستور را بزنید:

کد: انتخاب همه
find -cnewer /etc/fstab



مطمئن باشید که این گزینه ها روزی کمکتان خواهد کرد!

اجرای دستورات بر روی فایلهای پیدا شده

رسیدیم به مرحله جذاب کار! اینجاست که قدرت دستور find مشخص میشود.میتوان با گزینه -exec هر دستور دلخواهی را بر روی فایلهایی که دستور find پیدا کرده است، اجرا کنیم. عملیاتی که شما میتوانید بر روی فایلهای پیدا شده انجام دهید میتوانند این‌ها باشند:

* دستور rm برای پاک کردن
* دستور mv برای تغییر نام یا جابه جایی
* دستور md5sum برای محاسبه الگوریتم md5sum
* دستور wc برای شمارش فایلها
* اجرای هر دستور دلخواه دیگر
* اجرای شل اسکریپتی که خودتان نوشته‌اید.

سینتکس کلی بدین گونه است:

کد: انتخاب همه
find <PATH> <CONDITION to Find files> -exec <OPERATION> {} \;



بهتر است که مسیر کامل دستور را بنویسید. در غیر این صورت find از متغیر PATH برای پیدا کردن دستور استفاده میکند.در مثال زیر دستور md5sum بر روی تمام فایلها اجرا شده و الگوریتم md5sum آن فایلها را محاسبه میکند. برای اینکه بدانید {} چیست به مثال بعد توجه فرمایید.

کد: انتخاب همه
$ find -iname "MyCProgram.c" -exec md5sum {} \;
d41d8cd98f00b204e9800998ecf8427e ./mycprogram.c
d41d8cd98f00b204e9800998ecf8427e ./backup/mycprogram.c
d41d8cd98f00b204e9800998ecf8427e ./backup/MyCProgram.c



میخواهیم فایلهایی که myprogram.c نام دارند را پیدا کرده و سپس آن‌ها را در پوشهhome/$USERNAME/backup کپی کنیم. برای کپی فایلها باید از دستور cp استفاده کنیم. سینتکس دستور cp بدین صورت است.

کد: انتخاب همه
cp <SOURCE> <DESTINATION>



دقت کنید که دستور cp باید بداند که چه فایلهایی را به کجا کپی کند.
ولی در این مورد ما نمیدانیم که دقیقاً چه فایلهایی را میخواهیم کپی کنیم. برای حل این مشکل از {} استفاده میکنیم. عبارت {} توسط find تفسیر می‌شود و فایلهای پیدا شده جایگزین آن می‌شود و سپس به دستور cp ارسال می‌شود.

کد: انتخاب همه
find -iname "MyCProgram.c" -exec /bin/cp {} /home/$USERNAME/bakup \;



همانطور که میدانید برای اجرای هر دستور بعد از تایپ آن باید دکمه Enter را بزنیم. در پوسته کاراکتر ; معادل همان دکمه Enter یا newline است. در دستور find برای اجرا کردن دستور بر روی فایل ابتدا دستور را بعد از گزینه -exec مینویسیم، سپس کاراکتر ; را هم بعد از دستور مینویسیم. نوشتن این کاراکتر مانند این است که ما برای زدن آن دستور دکمه Enter را فشار داده‌ایم ( خود دستور find این کار را برای ما انجام نمیدهد). به خاطر اینکه پوسته این کاراکتر را به اشتباه تفسیر نکند، قبل از آن یک \ (بک اسلش) قرار میدهیم.

اگر میخواهید فایلهای پیدا شده را پاک کنید میتوانید از دستور زیر استفاده کنید:


کد: انتخاب همه
find . -name mycprogram -delete



گزینه -delete تمام فایلهای پیدا شده را پاک میکند.

نکته مهم: قبل از پاک کردن فایل مطمئن شوید که اشتباهاً چیز دیگری را پاک نمیکنید. یک بار دستور را بدون -delete اجرا کنید و بعد خروجی را چک کرده و مجدداً به همراه گزینه -delete دستور را اجرا کنید. همچنین گزینه -ok را هم ببینید.

نکته مهم: اجرای دستور بر روی فایلهای پیدا شده میتواند مدت زیادی طول بکشد. دستور زیر را در نظر بگیرید:

کد: انتخاب همه
find ~ -empty -exec /bin/rm {} \;



فرض کنید دستور بالا ۱۰۰۰ فایل را پیدا کند. بعد از پیدا کردن هر فایل یک بار دستور rm بر روی آن اجرا می‌شود. این گزینه میتواند در عمل‌کرد سیستم شما تأثیر منفی بگذارد. همچنین به دستور زیر نیز دقت کنید:

کد: انتخاب همه
find ~ -empty -print | xargs /bin/rm



تفاوت این دو دستور در این است که دستور اول بعد از هر بار پیدا شدن فایل فرمان /bin/rm را بر روی آن اجرا میکند و در نتیجه ۱۰۰۰ بار این فرمان بر روی ۱۰۰۰ فایل اجرا خواهد شد. ولی دستور دوم بعد از پیدا کردن همه فایلها فقط یک بار دستور rm را بر روی تمام آن‌ها اجرا میکند. یعنی یک بار دستور /bin/rm بر روی ۱۰۰۰ فایل انجام میشود. مشخص است که دستور دوم کارایی بهتری دارد. برای کسب اطلاعات بیشتر در مورد دستور xargs در خط فرمان man xargs را وارد کنید.

جستجو بر اساس فایل سیستم

مدیران سیستم دوست دارند که شاخه روت / را جستجو کنند ولی نه در بقیه فایل سیستم‌های مونت شده. مثلاً اگر یکی از پارتیشن ها در /mnt مونت شده باشد find آن پارتیشن را هم جستجو میکند. دستور زیر تمام پارتیشن های مونت شده را برای پیدا کردن فایلهایی که نام آن‌ها با .log ختم می‌شود را جستجو میکند.

کد: انتخاب همه
$ find / -name "*.log"




ولی اگر چند پارتیشن را در / مونت کرده‌اید میتوانید با گزینه -xdev به find بگویید که جستجو را در آن پارتیشن ها انجام ندهد.

کد: انتخاب همه
$ find / -xdev -name "*.log"



استفاده چند باره از {}
شما میتوانید چند بار از {} در دستورتان استفاده کنید. مانند زیر:

کد: انتخاب همه
$ find -name "*.txt" cp {} {}.bkup \;



ولی باید به این نکته توجه داشته باشید همه {} ها باید در یک دستور باشند و استفاده از آن در دستور متفاوت امکان‌پذیر نیست. مثلاً دستور زیر درست نیست و نتیجه دلخواه را برنمیگرداند:

کد: انتخاب همه
find -name "*.txt" -exec mv {} `basename {} .htm`.html \;




پیدا کردن فایل بر اساس مالک
اگر میخواهید فایلهایی را که یک کاربر خاص مالک آنهاست را پیدا کنید، میتوانید با گزینه -user آن را مشخص کنید. در حقیقت این گزینه جستجو را بر اساس مالک فایل انجام میدهد. دستور زیر تمام فایلهای مربوط به کاربر root را در دایرکتوری خانگی کاربر javad و زیر دایرکتوری هایش پیدا میکند.

کد: انتخاب همه
$ find /home/javad -user root



همچنین دستور زیر تمام فایلهایی را که متعلق به root نیستند را پیدا میکند.

کد: انتخاب همه
$ find ! -user root



پیدا کردن فایل بر اساس گروه
اگر میخواهید فایلهایی که متعلق به گروه خاصی هستند را پیدا کنید، میتوانید با گزینه -group آن را مشخص کنید. در حقیقت این گزینه جستجو را بر اساس گروه فایل انجام میدهد. دستور زیر تمام فایلهای متعلق به گروه root را پیدا میکند.

کد: انتخاب همه
$ find -group root



تعداد لینک
این امکان وجود دارد که جستجو را بر اساس تعداد لینکهای سخت یک فایل انجام دهید. همانطور که توضیح داده شد هر inode میتواند چند نام داشته باشد که به این نامها لینک سخت میگویند و تا زمانیکه تعداد لینکهای سخت یک فایل به صفر نرسد فایل به صورت فیزیکی بر روی دیسک باقی می ماندو پاک نمیشود.

با گزینه -links میتوانید جستجو را بر اساس تعداد لینکهای سخت انجام دهید مثلاً دستور زیر تمام فایلهایی را که بیشتر از ۳ لینک سخت دارندو از نوع f هستند پیدا میکند.

کد: انتخاب همه
$ find -type f -links +3



-readable
تعیین میکند که آیا فایل برای کاربری که دستور را اجرا کرده قابل خواندن است یا نه.

-writable
نمایش فایلهایی که برای کاربر اجرا کننده دستور قابل نوشتن هستند.

-executable
نمایش فایلهایی که برای کاربر اجرا کننده دستور قابل اجرا هستند.


-ok ;
همانند -exec است با این تفاوت که قبل از اجرای فرمان بر روی فایل از کاربر تأیید میگیرد و در صورتی که کاربر تأیید نکند فرمان بر روی فایل اجرا نمیشود. اگر میخواهید فرمان اجرا شود y و اگر می‌خواهید اجرا نشود n را بزنید. اگر قصد پاک کردن یا جابه جایی فایل را دارید بهتر است از این گزینه استفاده کنید.

-ls
این گزینه فرمان ls -dils را بر روی فایلهای پیدا شده اجرا می کند. خروجی این فرمان را در زیر مشاهده میکنید:

کد: انتخاب همه
$ find -type f -ls
1959066 5928 -rw-r--r-- 1 javad javad 6056096 Jun 4 03:45 ./ps.flv
1959053 2148 -rw-r--r-- 1 javad javad 2193553 Jun 4 03:38 ./cut.flv
1959052 1416 -rw-r--r-- 1 javad javad 1445462 Jun 4 03:28 ./bin.flv
1958514 2024 -rw-r--r-- 1 javad javad 2067468 May 27 03:33 ./chattr.flv


جالب است بدانید که گزینه -fls هم وجود دارد که همانند -ls است با این تفاوت که خروجی را در فایل ذخیره میکند. مثلاً :

کد: انتخاب همه
find -fls list



خروجی را در فایلی به نام list ذخیره میکند. اگر این فایل وجود نداشته باشد ساخته می‌شود و اگر وجود داشته باشد بر روی آن overwrite میشود.

-print
این گزینه باعث می‌شود که خروجی در (standard output) چاپ شود. البته بعد از هر فایل یک کاراکتر newline قرار میدهد تا هر فایل در یک سطر قرار گیرد. اگر خروجی find را به برنامه‌ای لوله بندی میکنید و در نام فایل کاراکتر newline وجود دارد، از -print0 استفاده کنید فایلها پشت سر هم قرار گیرند. این گزینه پیش‌فرض است.

-print0
نام کامل فایلها را در خروجی چاپ میکند و بین هر فایل یک کاراکتر null قرار میدهد (در عوض newline). با این کار اگر در نام فایل کاراکتر newline یا نوع دیگری از white space وجود داشته باشد، توسط برنامه‌هایی که خروجی find را میخوانند به درستی تفسیر شوند. همچنین معادل گزینه -0 در فرمان xargs است.

-fprint0
همانند -print0 فقط خروجی را به جای صفحه نمایش به یک فایل میفرستد. اگر فایل وجود نداشته باشد ایجاد و در صورت وجود overwrite میشود.

-fprint
همانند -print ولی خروجی رابه جای صفحه نمایش به یک فایل میفرستد. اگر فایل وجود نداشته باشد ایجاد و در صورت وجود overwrite میشود.

-samefile name
نمایش فایلهایی که به inode فایل name اشاره میکنند. فرض کنید دو لینک سخت از یک فایل داریم، اگر نام یک لینک را بدانید میتوانید لینک دیگر را هم پیدا کنید.

منابع: از سایت geekstuff و منوال دستور find
مجوز این مقاله GFDL هست.