قبل از مطالعه :
این راهنما را چند وقت پیش نوشته و در آدرس http://safarionline.ir/site/index.php?title=%D8%AF%D8%B3%D8%AA%D9%88%D8%B1_find منتشر کرده ام . فکر می کنم مخاطبان این نوشتار در این مکان بیشتر خواهد بود ولی به هر حال اگر مایل به مشاهده این متن در حالت نمایشی بهتر هستید می توانید به آدرس فوق هم مراجعه کنید.
مقدمهfind یکی از مهمترین دستورات یونیکس است که دیر یا زود به آن نیاز مبرمی پیدا می کنید . با یادگیری دستور find و به کار بردن عملی آن در کارهای روزانه ، هر روز می توانید کاربرد جدیدی برای آن پیدا کنید ، مثلا با اتصال خروجی این دستور به ورودی دستور دیگر از طریق pipe می توانید عملیات گوناگونی را روی فایل هایی که پیدا کرده اید انجام دهید و یا اینکه مستقیما از سوییچ exec- دستور find استفاده کنید . exec- برای تمامی فایل های یافته شده اجرا خواهد شد و می تواند شامل هر دستوری باشد . وقتی که در find خبره شدید احتمالا به خود خواهید گفت بدون find چطور زندگی می کردم ؟!
طرح چند پرسش- دنبال ویدیویی به نام moammaye_hasti.mp4 از شجریان می گردم ولی پیداش نمی کنم.
- فیلم های سینمایی من همه بالای ۶۰۰-۷۰۰ مگابایت هستن ولی متاسفانه توی فولدرهای مختلف گم شدن . از همه بدتر اینکه اسمشون رو هم چیزهای الکی گذاشتم مثلا ddd.mp4 یا london.mp4
- ماه گذشته دو تا سی دی کامل mp3 کپی کردم توی کامپیوتر ولی همه شون رو گم کردم !
- می خوام عکس های موجود در این دایرکتوری و زیر دایرکتورهاش رو پاک کنم ولی دایرکتوری خیلی بزرگه و پر از اطلاعات . حتی اگه وقتش رو داشته باشم و به صورت دستی این کار رو انجام بدم ، اون موقع همش ناراحت اینم که آیا همه عکس ها رو پاک کردم یا خدایی ناکرده چند تایی شون از دستم در رفته !
- می خوام لیست کل فایل های این دایرکتوری و کلیه زیر دایرکتوری های زیرش رو به دست بیارم . ls کمکی بهم نکرد.
- می خوام کلیه فایل هایی که owner شون reza هست رو به نام mohsen در بیارم . می دونم که باید از chown استفاده کنم ولی از کجا کلیه فایل های رضا رو شناسایی کنم و چه طوری اون همه chown بنویسم ؟
جواب این چند پرسش و بسیاری پرسش های دیگر دستور find هست .جستجوی کلیه فایل هاشکل کلی و ساده دستور find به صورت زیر است :
$ find path experssion
path مسیر مورد جستجو است . جستجو در کلیه دایرکتوری های زیر مجموعه path به صورت تو در تو (recursive) و تا آخرین دایرکتوری انجام می شود مگر اینکه عمق جستجو را معلوم کرده باشیم که در این صورت ، جستجو تا عمق انتخاب شده انجام خواهد شد . عمق جستجو با استفاده از سوییچ d- ( ابتدای کلمه depth ) مشخص می شود .
$ find path -d 3 other-experssions
در دستور بالا find تا سه زیر دایرکتوری را جستجو می کند .
- لیست کلیه فایل ها و دایرکتوری های خانه ( و زیر دایرکتوری های آن )
$ find ~
این دستور فاقد experssion است و به صورت اتوماتیک لیست فایل های یافت شده را در خروجی استاندارد چاپ می کند . ~ ( تیلدا ) نشان دهنده دایرکتوری خانه کاربر جاری می باشد .
جستجو بر مبنای نام فایلبرای جستجو بر مبنای نام از دو سوییچ name- و iname- استفاده می کنیم . حرف i در ابتدای سوییچ iname- ابتدای کلمه case-insensitive است به این معنا که کوچکی و بزرگی حروف اهمیتی ندارد . چنانچه در عبارتی که جلوی سوییچ ها نوشته می شود از wildcard استفاده نکرده باشیم ، find دقیقا عبارت مورد نظر را جستجو می کند . در صورت استفاده از wildcard دستور find بر مبنای wildcard تصمیم گیری می کند . * به معنای هر تعداد کاراکتر و ? به معنای دقیقا یک کاراکتر می باشد .
- جستجو کردن فایل moammaye_hasti.mp3 در دایرکتوری خانگی ( و زیر دایرکتوری های آن )
$ find ~ -iname "moammaye_hasti.mp3"
برای اینکه جستجو ، هم فایلهای با حروف کوچک و هم فایل های با حروف بزرگ را شامل شود از سوییچ iname- استفاده می کنیم . اگر از اسم فایل اطمینان دارید می توانید نام را دقیقا مانند نام فایل بنویسید و از سوییچ name- استفاده کنید.
- جستجو کردن کلیه فایل های mp3 علی
$ find ~ali -iname "*.mp3"
- جستجو کردن کلیه فایل های پنهان موجود در دایرکتوری جاری و زیر دایرکتوریهای آن
$ find . -name ".*"
می دانید که فایل پنهان فایلی است که با دات (.) شروع شود .
- کلیه فایل ها و دایرکتوری های سه حرفی را نمایش بده . زیر دایرکتوری ها را جستجو نکن .
$ find ~ -name "???" -d 1
فراموش نکنید چنانچه از * و یا ? استفاده می کنید حتما متن را با استفاده از "" و یا ′′ quote کنید و یا اینکه قبل از کاراکتر ویژه * و یا ? علامت \ قرار دهید و یا به عبارت دیگر آن را escape کنید .
ارسال خروجی find به xargsتا به حال با پیغام arguments too long مواجه شده اید ؟ علت این پیغام چیست ؟ در واقع پوسته یا shell تا حد معینی می تواند آرگومانهای خط فرمان را به برنامه فراخوانده شده ارسال کند . وقتی این تعداد از حد معین شده توسط پوسته بیشتر می شود ، پوسته پیغام arguments too long می دهد . برای حل این مشکل و البته برای کاربرد در وضعیتهای دیگر دستور xargs به کمک می آید .
$ ls | xargs echo
xargs محتوای خوانده شده از ورودی استاندارد را به عنوان آرگومان به دستور خواسته شده می فرستند . در دستور فوق ورودی استاندارد به سمت pipe تغییر جهت یافته است و لذا xargs محتوای ارسالی در pipe ، که همان خروجی دستور ls است را می خواند و آن را به عنوان آرگومانهای ورودی به دستور echo ارسال می کند . xargs محدودیت تعداد آرگومان پوسته را می داند و لذا دیگر شاهد پیغام arguments too long نخواهید بود .
- برای حذف کلیه فایل های mp3 از دایرکتوری جاری به شیوه زیر نیز می توان عمل کرد :
$ ls *.mp3 | xargs rm
دستور ls کلیه فایلهای خاتمه یافته به پسوند mp3 را لیست می کند و آن را به pipe می فرستد . xargs از pipe می خواند و محتوای خوانده شده را به عنوان آرگومانهای دستور rm منظور می کند و سپس rm را اجرا می کند . اگر لیست فایل های mp3 بسیار زیاد باشد در این صورت xargs یکبار دستور rm را با تعداد کافی آرگومان خوانده شده از پایپ اجرا می کند و سپس دوباره اقدام به اجرای دستور rm با آرگومانهای جدید می نماید . این عمل تا زمانی که pipe خالی شود ادامه می یابد .
- دستور بالا را می توان با استفاده از find نوشت . توجه کنید چون find جستجو را به صورت تو در تو انجام می دهد برای پیاده سازی دقیق دستور بالا باید عمق جستجو را ۱ بگذاریم .
$ find . -d 1 -iname "*.mp3" | xargs rm
عمق جستو با سوییچ d- مشخص می شود .
متاسفانه دستور xargs در مورد فایل هایی که در نامشان space دارند درست عمل نمی کند .
حل مشکل space در xargs و findدستور xargs بر مبنای کاراکترهای space و new line کار می کند ، یعنی اگر میان نام یک فایل space باشد xargs آن را به چند نام تقسیم می کند ، چون کارکتر جداکننده آن space است .
خوشبختانه دستور find دارای سوییچی به نام print0- می باشد که در آخر تمام موارد یافته شده کاراکتر NULL را قرار می دهد و همچنین دستور xargs نیز دارای سوییچی به نام 0- می باشد که کاراکتر جدا کننده را به NULL تغییر می دهد .
- دو دستور زیر و خروجی های آن ها را ملاحظه بفرمایید .
$ find . -name "Untitled 1.odt" | xargs ls -l
ls: ./Untitled: No such file or directory
ls: 1.odt: No such file or directory
$ find . -name "Untitled 1.odt" -print0 | xargs -0 ls -l
-rw-r--r-- 1 mohsen wheel 31308 Apr 1 17:33 ./Untitled 1.odt
جستجو بر مبنای نوع (type) فایلگاهی اوقات نیاز به جستجو در میان نوع خاصی از فایل ها داریم . برای این منظور از سوییچ type- به همراه کاراکترهای تعریف شده زیر استفاده می کنیم .
b : فایل ویژه از نوع block یا block special file
c : فایل ویژه از نوع character یا character special file
d : دایرکتوری
f : فایل معمولی
l : لینک
s : سوکت socket
- لیست کلیه فایل های معمولی در دایرکتوری جاری و لیست کامل اطلاعات آن
$ find . -type f -d 1 | xargs ls -l
- لیست کلیه لینک ها در دایرکتوری خانگی ( و زیر دایرکتوری های آن )
$ find ~ -type l
- لینک های موجود در دایرکتوری خانگی به کجا اشاره می کنند ؟
$ find ~ -d 1 -type l | xargs ls -l | awk '{print $9 " " $10 " " $11}'
علامت + و -علامت + به کار رفته قبل از عدد به معنای بزرگتر از یا بیشتر از می باشد . علامت - به کار رفته قبل از عدد به معنای کوچکتر از یا کمتر از می باشد .
عبارت size -20M- یعنی سایز فایل کمتر از ۲۰ مگابایت باشد و عبارت mtime -2- یعنی تاریخ ویرایش فایل کمتر از ۲ روز گذشته باشد .
عبارت size +100K- یعنی فایلهایی که سایزشان بیشتر از ۱۰۰ کیلو بایت باشد و عبارت atime +2- یعنی فایلهایی که تاریخ آخرین دسترسی به آنها بیشتر از ۲ روز گذشته باشد .
جستجو بر مبنای بزرگی (size) فایلبرای جستجو بر مبنای سایز از سوییچ size- استفاده می کنیم . به دنبال size- عدد صحیحی می آید . چنانچه این عدد بدون هیچ گونه کاراکتر بعدی باشد به معنای تعداد دقیق بلاک اشغال شده توسط برنامه می باشد . متاسفانه فضای هر بلاک برای برنامه های مختلف متفاوت است . مثلا در سیستم FreeBSD که من استفاده می کنم دستور ls -s که تعداد بلاک هر فایل را بر می گرداند هر بلاک را ۱۰۲۴ بایت حساب می کند در صورتیکه هر بلاک دستور find تعداد ۵۱۲ بایت می باشد .
$ ls -ls 5.txt
4 -rw-r--r-- 1 mohsen wheel 1058 Apr 6 21:25 5.txt
دستور فوق نشان می دهد که فایل 5 دارای 1058 بایت است و 4 بلاک اشغال کرده است . دستور ls بلاک ها را در واحدهای چهار تایی اختصاص داده است در حالیکه تعداد بلاک مصرف شده واقعی با حجم هر بلاک 1024 بایت دو بلاک است . ولی دستور find بلاکها را ۵۱۲ بایت حساب می کند لذا عدد بلاک مصرف شده برای این فایل از نظر دستور find تعداد ۳ بلاک است . این موضوع را با دستور زیر تست می کنیم .
$ find -size 3 | xargs ls -ls
4 -rw-r--r-- 1 mohsen wheel 1058 Apr 6 21:25 ./5.txt
موضوع پیجیده شد ؟ خوشبختانه راههای فرار خوبی وجود دارد ! می توان بعد از عدد صحیح از کاراکترهای زیر استفاده کرد.
c : کاراکتر . مثلا 27c یعنی ۲۷ کاراکتر یا ۲۷ بایت
k : کیلو بایت . مثلا 27k یعنی ۲۷ کیلو بایت . ( توجه کنید k با حرف کوچک نوشته شده است )
M : مگا بایت . مثلا 27M یعنی ۲۷ مگا بایت
G : گیگا بایت . مثلا 27G یعنی ۲۷ گیگا بایت
T : ترا بایت . مثلا 27T یعنی ۲۷ ترا بایت
P : پتا بایت . مثلا 27P یعنی ۲۷ پتا بایت
- لیست فایلهای MP4 که سایز آنها بیشتر از ۶۰۰ مگا بایت است :
$ find ~ -type f -iname "*.mp4" -size +600M
- لیست فایلهای jpg که بین ۴۰۰ کیلو بایت تا ۵ مگابایت هستند :
$ find ~ -type f -iname "*.jpg" -size +400k -size -5M
دستور بالا نشان می دهد که زمانی که دو یا چند شرط وجود داشته باشند تمامی شرط ها می بایست true باشند یا به عبارت دیگر شرط ها با هم AND می شوند .
جستجو بر مبنای سطح دسترسی (permission) فایلسوییچ perm- برای یافتن فایل با سطوح دسترسی مشخص استفاده می شود . عدد قرار گرفته در جلو سوییچ می بایست عددی در مبنای ۸ باشد .
- فایل های دارای اجازه دسترسی ۷۷۷ را نمایش بده
$ find ~ -perm 777
- فایل های دارای اجازه دسترسی ۷۵۵ را نمایش بده
$ find ~ -perm 755
بعضی اوقات نیازی به دانستن اجازه دسترسی کامل فایل ندارید و فقط یک مجوز برای شما مهم است . مثلا می خواهید بدانید گروه در کدام فایل ها اجازه نوشتن دارد . برای این موارد سریعا ترکیب rwx rwx rwx را برای فایل مورد نظر تشکیل دهید . بدیهی است که rwx ها به ترتیب از چپ به راست مجوزهای صاحب فایل ، گروه و دیگران هستند . زیر مجوز هایی که برای شما اهمیتی ندارند صفر بگذارید و مجوز های که لازم است داشته باشند را یک قرار دهید . عدد حاصله را در مبنای هشت بنویسید و با یک علامت - پیش از آن ، جلوی سوییچ perm- قرار دهید .
علامت - پیش از عدد permission می گوید که اجازه دسترسی واقعی فایل را با عدد جلوی permission به صورت بیتی AND کن و اگر حاصل درست بود فایل را نمایش بده ( یعنی آن فایل مجوزی که برای شما مهم بوده است را دارد. )
- کدام فایل ها مجوز نوشتن توسط گروه را دارند ؟
rwx rwx rwx
000 010 000
عدد هشت بیتی حاصل 020 می باشد . از این عدد به صورت زیر استفاده می کنیم .
$ find ~ -perm -020
- لیست کامل فایل های اجرایی را نمایش بده .
rwx rwx rwx
001 000 000
عدد هشت بیتی حاصل 001 می باشد .
$ find ~ -type f -perm -001
سوییچ perm- همچنین قابلیت شناسایی بیت های SUID و SGID و sticky bit را نیز دارد . برای این منظور فقط کافیست ترکیب SUID SGID sticky را در سمت چپ rwx صاحب فایل تشکیل دهید و مانند سابق عدد هشت بیتی حاصل را با علامت - بعد از سوییچ perm- قرار دهید .
- تمام فایل هایی که بیت SUID آن فعال است را پیدا کن .
SUID/SGID/sticky rwx rwx rwx
000 000 000 0 0 1
عدد هشت بیتی حاصل 4000 می باشد .
$ find /usr/bin -type f -perm -4000 -print0 | xargs -0 ls -lh | head -n 5
-r-sr-xr-x 4 root wheel 22k Dec 4 2012 /usr/bin/at
-r-sr-xr-x 4 root wheel 22k Dec 4 2012 /usr/bin/atq
-r-sr-xr-x 4 root wheel 22k Dec 4 2012 /usr/bin/atrm
-r-sr-xr-x 4 root wheel 22k Dec 4 2012 /usr/bin/batch
-r-sr-xr-x 6 root wheel 18k Dec 4 2012 /usr/bin/chfn
گاهی اوقات می خواهید فایل هایی را پیدا کنید که مجوز خاصی را نداشته باشند . برای اینگونه موقعیت ها باید ابتدا شرط داشتن مجوز را بنویسید و سپس آن شرط را نقیض کنید . برای این منظور در بخش های بعد عملگرهای منطقی را بررسی خواهیم کرد .
جستجو بر مبنای زمان ویرایش ، زمان دسترسی و زمان تغییر i-nodeبه طور کلی جستجوی زمانی را بر مبنای دو پارامتر روز و دقیقه انجام می دهیم .
جستجو بر مبنای روز
سوییج های جستجو بر مبنای روز به صورت زیر تعریف می شوند :
mtime- : برگرفته از عبارت modified time یا زمان آخرین ویرایش فایل . از آنجایی که یونیکس زمان ایجاد فایل را ذخیره نمی کند به عنوان زمان ایجاد فایل هم می تواند استفاده شود .
atime- : برگرفته از عبارت accessed time یا زمان آخرین دسترسی به فایل .
ctime- : بر گرفته از عبارت i-node change time یا زمان آخرین تغییر اطلاعات i-node . چنانچه نام فایل ، صاحب فایل ، گروه و یا تعداد لینک های داده شده به فایل و ... تغییر کند بدون اینکه محتوای فایل مورد ویرایش قرار گیرد این تاریخ زمانی جلوتر از زمان آخرین ویرایش فایل خواهد داشت .
- فایل هایی که ۷ روز پیش ویرایش شده را نمایش بده .
$ find ~ -mtime 7
همین مثال می تواند به صورت زیر با استفاده از علامت های + و - نیز نوشته شود.
$ find ~ -mtime +6 -mtime -7
یعنی زمان ویرایش فایل بیشتر از ۶ روز و کمتر از 7 روز پیش باشد. علامت + شامل همان عدد نمی شود ولی علامت - خود عدد را نیز شامل می شود.
- فایل هایی که بیشتر از ۳۰ روز است که از آنها استفاده نکرده ام .
$ find ~ -atime +30 -type f
- نمایش فایل هایی که بیشتر از یک روز پیش و کمتر از دو روز پیش به آن ها دسترسی داشته ام .
$ (echo -e current date : `date` "\n";find . -type f -d 1 -atime -2 -atime +1 -print0 | xargs -0 ls -lut)
current date : Fri Apr 11 16:15:37 IRDT 2014
-rw-r--r-- 1 mohsen wheel 11710 Apr 9 23:20 ./b.result
-rw-r--r-- 1 mohsen wheel 155845071 Apr 9 23:13 ./download36.mp4
-rw-r--r-- 1 mohsen wheel 1292918 Apr 9 18:01 ./b.flv
-rw-r--r-- 1 mohsen wheel 2168490 Apr 9 18:01 ./recovered2.flv
-rw-r--r-- 1 mohsen wheel 3022870 Apr 9 18:00 ./recovered1.flv
همانطوری که مشاهده می کنید علامت + شامل خود عدد ( در اینجا ۱ روز ) نمی شود ولی علامت منفی شامل عدد ( در اینجا ۲ روز ) می شود .
جستجو بر مبنای دقیقهسه سوییچ زیر برای جستجو بر مبنای دقیقه مورد استفاده قرار می گیرند :
mmin- : بر گرفته از عبارت modified minute
amin- : بر گرفته از عبارت accessed minute
cmin- : برگرفته از عبارت i-node change minute
کاربرد این سوییچ ها دقیقا مانند سوییچ های بخش قبل هستند با این تفاوت که همه چیز در اینجا معنای دقیقه می دهد .
- فایلهایی که کمتر از ۶۰ دقیقه قبل ویرایش شده اند را نمایش دهید .
$ find . -type f -mmin -60
- فایل هایی که کمتر از ۴۰ دقیقه پیش آن ها را مشاهده کرده ام را نمایش دهید .
$ find . -type f -amin -40
جستجوی زمانی بر مبنای زمان ویرایش یک فایلاگر می خواهید متوجه شوید زمان آخرین ویرایش چه فایل هایی از فایل داده شده کمتر است از سوییچ newer- استفاده کنید.
- چه فایل هایی از فایل tmp.sh جدیدتر می باشند ؟
$ ls -l tmp.sh
-rwxr-xr-x 1 mohsen wheel 34 Mar 24 21:56 tmp.sh*
$ find . -d 1 -newer tmp.sh | xargs ls -lt | head -n 5
-rw-r--r-- 1 mohsen wheel 0 Apr 11 19:05 ./4
-rw-r--r-- 1 mohsen wheel 0 Apr 11 19:05 ./3
-rwxr-xr-x 2 mohsen wheel 2 Mar 30 22:40 ./1
-rwxr-xr-x 2 mohsen wheel 2 Mar 30 22:40 ./2
lrwxr-xr-x 1 mohsen wheel 21 Mar 30 17:08 ./.profile -> /home/mohsen/.profile
جستجو بر مبنای صاحب (owner) و گروه (group) فایلاز سوییچ user- برای جستجوی فایلها بر مبنای نام کاربری یا شماره یکتای صاحب فایل استفاده می شود . شماره یکتای هر کاربر را می توانید در فایل etc/passwd/ مشاهده کنید .
$ cat /etc/passwd | grep ^mohsen
mohsen:*:1001:1001:Mohsen Safari:/home/mohsen:/usr/local/bin/bash
مثال بالا خط مربوط به کاربر mohsen در فایل etc/passwd/ را نشان می دهد که دارای شماره کاربری ۱۰۰۱ می باشد .
از سوییچ group- برای جستجوی فایلها بر مبنای نام گروه و یا شماره ی یکتای گروه استفاده می شود . شماره یکتای هر گروه را می توانید در فایل etc/group/ مشاهده کنید .
$ cat /etc/group | grep ^mohsen
mohsen:*:1001:
در مثال بالا مشاهده می کنید که گروه mohsen دارای شماره یکتای ۱۰۰۱ می باشد .
- کلیه فایل هایی که SGID آن ها به wheel ست شده است را پیدا کنید .
$ find ~ -group wheel -perm -2000
جستجو بر مبنای i-numberتا به حال دستور ls -li را اجرا کرده اید ؟ نمونه خروجی این دستور را ببینید :
$ ls -li
total 64
11397272 drwxr-xr-x 6 mohsen wheel 512 Apr 5 20:23 ./
11318506 drwxr-xr-x 3 mohsen wheel 512 Mar 21 21:34 ../
11396871 lrwxr-xr-x 1 mohsen wheel 21 Mar 30 17:08 .profile@ -> /home/mohsen/.profile
11396876 -rw-r--r-- 2 mohsen wheel 2 Mar 30 22:40 1
11396876 -rw-r--r-- 2 mohsen wheel 2 Mar 30 22:40 2
11396865 -rwxr-xr-x 1 mohsen wheel 34 Mar 24 21:56 2.2.sh*
11879926 drwxr-xr-x 3 mohsen wheel 512 Mar 30 18:12 DIR/
11396862 -rw-r--r-- 1 mohsen wheel 252 Mar 24 20:51 args-no.sh
11396866 -rwxr-xr-x 1 mohsen wheel 2054 Mar 23 16:02 cleanup*
12039467 drwxrwxr-x 2 mohsen wheel 512 Apr 5 20:23 d1/
12039468 dr-xr-xr-x 2 mohsen wheel 512 Apr 5 20:23 d2/
12039469 drwxr-xr-x 2 mohsen wheel 512 Apr 5 20:23 d3/
11396867 -rw-r--r-- 1 mohsen wheel 352 Mar 24 21:49 log
11396875 -rwxr-xr-x 1 mohsen wheel 8780 Mar 24 20:59 readme*
11396878 -rwxr-xr-x 1 mohsen wheel 403 Mar 21 22:11 swap.sh*
عدد های قرار گرفته در سمت چپ هر سطر i-number نامیده می شود و شماره درایه مربوط به آن فایل در داخل جدول i-table یا inode-table می باشند .
دستور find قابلیت جستجو بر مبنای i-number را دارد . برای این منظور می توانید از سوییچ inum- استفاده کنید . می بایست بعد از inum- شماره i-number فایل مورد را قرار دهید .
- فایل دارای i-number به شماره ۱۱۳۹۶۸۶۶ را از طریق دستور find بیابید .
$ find . -inum 11396866 | xargs ls -li
11396866 -rwxr-xr-x 1 mohsen wheel 2054 Mar 23 16:02 ./cleanup
برای مشاهده صحت عملکرد find خروجی آن را از طریق pipe به دستور xargs ls -li ارسال می کنیم . سوییچ i در دستور ls همانگونه که می دانید شماره i-number هر فایل را بر می گرداند .
جستجوی فایل های خالی (empty)از سوییچ empty- برای یافتن فایل های خالی استفاده می شود .
$ >1 ; >2 ; >3
$ echo "salam" >4
$ find . -empty | xargs ls -l
-rw-r--r-- 1 mohsen wheel 0 Apr 7 15:32 ./1
-rw-r--r-- 1 mohsen wheel 0 Apr 7 15:32 ./2
-rw-r--r-- 1 mohsen wheel 0 Apr 7 15:32 ./3
همانطور که در ریز لیست فایل ها می بینید حجم تمام این فایل ها صفر بایت است و در واقع خالی هستند .
- از سوییچ empty- برای یافتن دایرکتوری های خالی هم می توان استفاده کرد .
$ mkdir newdir
$ echo "salam" >newdir/1.txt
$ mkdir emptydir
$ find . -type d -empty
./emptydir
سوییچ exec- و ok-تا کنون برای ارسال خروجی دستور find به برنامه های دیگر از pipe و xargs استفاده کرده ایم ولی این شیوه تنها راه حل نیست بلکه می توانیم از سوییچ exec- خود دستور find استفاده کنیم . بعد از exec- می توانیم هر دستوری را استفاده کنیم .
- سوییچ ok- دقیقا مانند سوییچ exec- است با این تفاوت که قبل از اجرای دستور از شما می پرسد که آیا دستور را اجرا کند یا خیر.
- متغیر {} در سوییچ exec- به معنای نام فایل یافته شده می باشد . با یافتن نتیجه جدید مقدار {} رونویسی می شود .
- exec- یکبار به ازای هر فایل یافته شده اجرا می شود به عنوان مثال اگر جستجویی ۴۰ نتیجه داشته باشد و در این جستجو از سوییج exec- استفاده کرده باشیم ، exec- چهل بار اجرا خواهد شد ، در صورتیکه با استفاده از pipe و xargs ، دستور xargs چهل نتیجه یافته شده را به عنوان آرگومان دستور بعدی منظور کرده و به احتمال بسیار زیاد فقط یکبار دستور مورد نظر را اجرا می کند . از طرف دیگر xargs در مورد فایلهایی که در داخل نامشان space دارند به صورت پیش فرض درست عمل نمی کند ( مشاهده راه حل ) و در این مواقع بهتر است از سوییچ exec- استفاده کنید . تصمیم گیری در مورد استفاده از xargs یا سوییچ exec- با توجه به شرایط و تجربه با شما خواهد بود .
- بعد از سوییج exec- دستوری می آید که در صورت پیدا شدن یک فایل اجرا خواهد شد . از آنجا که این دستور باید مستقیما و به طور کامل به دستور find ارسال شود تا در موقع لزوم اجرا شود ، می بایست کلیه کاراکترهایی که shell آن ها را تفسیر می کند را escape کنیم . از جمله این کاراکترها سمی کالن و * و ( و ) و ? می باشند . برای escape کردن این کاراکترها قبل از آنها یک \ قرار دهید . از طرفی find می بایست نقطه پایان دستور exec- را شناسایی کند . برای نشان دادن نقطه پایان دستور exec- از ; استفاده می کنیم . ; در پوسته به معنای جدا کننده دستورها می باشد لذا ; نیز می بایست escape شود .
- فایل های mp3 دایرکتوری جاری و زیر داکتوری های آن را حذف کنید . لطفا قبل از حذف از من سوال کنید.
$ find . -iname "*.mp3" -ok rm {} \;
دستور فوق فایل های mp3 را یافته و بعد از پرسیدن اینکه آیا دستور اجرا شود یا خیر ، در صورت موافقت ، دستور rm را روی فایل مورد نظر ( {} ) اجرا می کند . ok- به ازای هر نتیجه یکبار از شما می پرسد که آیا دستور را اجرا کند یا خیر . بنابر این شما می توانید دستور را روی بعضی از فایل ها اجرا کنید و روی بعضی فایل ها اجرا نکنید .
- از کلیه فایل های txt در دایرکتوری فعلی backup بگیرید .
$ find . -d 1 -iname "*.txt" -exec mv {} {}.bak \;
- متاسفانه در اثر بی دقتی فایلی به صورت زیر ایجاد شده است که حاوی تعداد زیادی space می باشد . چه طور می توانم آنرا حذف کنیم .
$ ls -li
12039479 -rw-r--r-- 1 mohsen wheel 0 Apr 7 16:02 o o
ساده ترین راه استفاده از دستور find به همراه سوییچ های inum- و exec- می باشد .
$ find . -inum 1203979 -exec rm {} \;
شیوه بالا برای انجام هر گونه عملیات روی فایلهایی که دارای کاراکترهای ویژه هستند و یا اینکه نامشان در ترمینال به درستی نمایش داده نمی شود مناسب است .
- مجوز کلیه فایل های داخل دایرکتوری جاری که با عدد شروع می شوند را به ۷۵۵ تغییر دهید .
$ find . -d 1 -name "[0-9]*" -type f -exec chmod 755 {} \;
استفاده از AND و OR و NOTبه صورت پیش فرض کلیه شرط های موجود در دستور find با هم AND می شوند ولی ما می توانیم با استفاده از چند سوییچ و عملگر ! روند پیش فرض find را تغییر دهیم .
عملگر ! قبل از شرط به معنای نقیض شرط مشخص شده می باشد .
- فایل هایی که بزرگتر از ۳۴ کاراکتر نیستند را نمایش بدهید .
$ find . -d 1 -size -34c
$ find . -d 1 ! -size +34c
دو دستور فوق تاحدودی معادل یکدیگر می باشند . دستور اول می گوید سایز فایل کمتر از ۳۴ کاراکتر و دستور دوم می گوید سایز فایل بیشتر از ۳۴ کاراکتر نباشد ولی دستور اول فایل های ۳۴ کاراکتری را نشان نمی دهد ولی دستور دوم نشان می دهد .
سوییچ a- به معنای AND و سوییچ o- به معنای OR می باشد . شرط ها را می توانیم با پرانتز گروه بندی کنیم . فراموش نکنید به علت اینکه پرانتز برای پوسته معنا دارد آنرا حتما با \ (بک اسلش) escape کنید .
- فایل هایی که در اسمشان حسن یا حسین می باشد را نمایش بدهید .
$ find . \( -iname "*hassan*" -o -iname "*hossein*" \)
دستور فوق می تواند به صورت زیر نیز نوشته شود .
$ find . -iname "*hassan*" -print -o -iname "*hossein*" -print
- فایل هایی که دیگران اجازه هیچ گونه دسترسی به آن را ندارند نمایش بدهید .
$ find . -d 1 ! \( -perm -001 -o -perm -002 -o -perm -004 \) -print0 | xargs -0 ls -ld
-rwxr-x--- 1 mohsen wheel 0 Apr 12 16:10 ./1
-rwxr-x--- 1 mohsen wheel 0 Apr 12 16:10 ./2
-rwxr-x--- 1 mohsen wheel 0 Apr 12 16:10 ./3
-rwxr-x--- 1 mohsen wheel 0 Apr 12 16:10 ./4
دستور فوق می تواند به صورت زیر نیز نوشته شود :
$ find . -d 1 ! -perm 001 ! -perm 002 ! -perm -004 -print0 | xargs -0 ls -ld
-rwxr-x--- 1 mohsen wheel 0 Apr 12 16:10 ./1
-rwxr-x--- 1 mohsen wheel 0 Apr 12 16:10 ./2
-rwxr-x--- 1 mohsen wheel 0 Apr 12 16:10 ./3
-rwxr-x--- 1 mohsen wheel 0 Apr 12 16:10 ./4
پاسخ پرسش های مطرح شده
- پیدا کردن ویدیوی moammaye_hasti.mp4
$ find ~ -type f -iname "moammaye_hasti.mp4"
- یافتن ویدیوهای حجیم با حجم بالای ۶۰۰ مگا بایت
$ find ~ -type f -size +600M
- پیدا کردن mp3 هایی که ماه گذشته ریخته بودم توی کامپیوتر . فکر می کنم بین ۳۰ تا ۳۵ روز گذشته بود؟!
$ find ~ -type f -iname "*.mp3" -ctime +29 -ctime -35
- حذف کردن عکسها . عکسهام همه پسوند jpg دارند . اگر هم نداشته باشند راحتترم که چند بار دستور find رو برای حذف پسوندهای مختلف صدا بزنم .
$ find ~/doc/BBAABB -type f -iname "*.jpg" -exec rm {} \;
- لیست کل فایل های دایرکتوری خانه و زیر دایرکتوری های آن . جایی که ls به راحتی کمک نمی کنه !
$ find ~ -type f
- فایل های رضا را به محسن تغییر مالکیت بده
$ find ~ -user reza -ok chown mohsen {} \;
دستور بالا به شرطی اجرا خواهد شد که مجوز های لازم را داشته باشید .