ورود به سایت

لطفا با نام کاربری و کلمه عبور وارد سایت شوید.

ثبت نام ×

لطفا فرم را پر کرده و ثبت نام کنید!

راهنمای دستور find

فهرست مطالب [ پنهان کردن ]
مقدمه
طرح چند پرسش
جستجوی کلیه فایل ها
جستجو بر مبنای نام فایل
ارسال خروجی find به xargs
حل مشکل space در xargs و find
جستجو بر مبنای نوع (type) فایل
علامت + و -
جستجو بر مبنای بزرگی (size) فایل
جستجو بر مبنای سطح دسترسی (permission) فایل
جستجو بر مبنای زمان ویرایش ، زمان دسترسی و زمان تغییر i-node
     جستجو بر مبنای روز
     جستجو بر مبنای دقیقه
     جستجوی زمانی بر مبنای زمان ویرایش یک فایل
جستجو بر مبنای صاحب (owner) و گروه (group) فایل
جستجو بر مبنای i-number
جستجوی فایل‌های خالی (empty)
سوییچ exec- و ok-
استفاده از AND و OR و NOT
پاسخ پرسش های مطرح شده

مقدمه

find یکی از مهمترین دستورات یونیکس است که دیر یا زود به آن نیاز مبرمی پیدا می‌کنید. با یادگیری دستور find و به کار بردن عملی آن در کارهای روزانه، هر روز می‌توانید کاربرد جدیدی برای آن پیدا کنید، مثلا با اتصال خروجی این دستور به ورودی دستور دیگر از طریق pipe می‌توانید عملیات گوناگونی را روی فایل‌هایی که پیدا کرده‌اید انجام دهید و یا اینکه مستقیما از سوییچ exec- دستور find استفاده کنید. exec- بر روی تمامی فایل‌های یافته شده اجرا خواهد شد و می‌تواند شامل هر دستوری باشد. وقتی که در find خبره شدید احتمالا به خود خواهید گفت بدون find چطور زندگی می‌کردم؟!

طرح چند پرسش

  • دنبال ویدیویی به نام moammaye_hasti.mp4 از شجریان می‌گردم ولی پیداش نمی‌کنم.
  • فیلم‌های سینمایی من همه بالای ۶۰۰-۷۰۰ مگابایت هستن ولی متاسفانه توی فولدرهای مختلف گم شدن. از همه بدتر اینکه اسمشون رو هم چیزهای الکی گذاشتم مثلا ddd.mp4 یا london.mp4
  • ماه گذشته دو تا سی دی کامل mp3 کپی کردم توی کامپیوتر ولی همه‌شون رو گم کردم!
  • می‌خوام عکس‌های موجود در این دایرکتوری و زیر دایرکتورهاش رو پاک کنم ولی دایرکتوری خیلی بزرگه و پر از اطلاعات. حتی اگه وقتش رو داشته باشم و به صورت دستی این کار رو انجام بدم، اون موقع همش ناراحت اینم که آیا همه عکس‌ها رو پاک کردم یا خدایی ناکرده چند تایی‌شون از دستم در رفته!
  • می‌خوام لیست کل فایل‌های این دایرکتوری و کلیه زیر دایرکتوری‌های زیرش رو به دست بیارم. ls کمکی بهم نکرد.
  • می‌خوام کلیه فایل‌هایی که owner شون reza هست رو به نام mohsen در بیارم. می دونم که باید از chown استفاده کنم ولی از کجا کلیه فایل‌های رضا رو شناسایی کنم و چه طوری اون همه chown بنویسم؟

جواب این چند پرسش و بسیاری پرسش‌های دیگر دستور find هست.

جستجوی کلیه فایل ها

شکل کلی و ساده دستور find به صورت زیر است:

Bash
$ find path experssion

path مسیر مورد جستجو است. جستجو در کلیه دایرکتوری های زیر مجموعه path به صورت تو در تو (recursive) و تا آخرین دایرکتوری انجام می‌شود مگر اینکه عمق جستجو را معلوم کرده باشیم که در این صورت، جستجو تا عمق انتخاب شده انجام خواهد شد. عمق جستجو با استفاده از سوییچ d- ( ابتدای کلمه depth ) مشخص می‌شود.

Bash
$ find path -d 3 other-experssions

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

لیست کلیه فایل‌ها و دایرکتوری‌های خانه (و زیر دایرکتوری های آن)

Bash
$ find ~

این دستور فاقد experssion است و به صورت اتوماتیک لیست فایل‌های یافت شده را در خروجی استاندارد چاپ می کند. ~ ( تیلدا ) نشان دهنده دایرکتوری خانه کاربر جاری می‌باشد.

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

برای جستجو بر مبنای نام از دو سوییچ name- و iname- استفاده می‌کنیم. حرف i در ابتدای سوییچ iname- ابتدای کلمه case-insensitive است به این معنا که کوچکی و بزرگی حروف اهمیتی ندارد. چنانچه در عبارتی که جلوی سوییچ‌ها نوشته می‌شود از wildcard استفاده نکرده باشیم، find دقیقا عبارت مورد نظر را جستجو می‌کند. در صورت استفاده از wildcard دستور find بر مبنای wildcard تصمیم گیری می‌کند. * به معنای هر تعداد کاراکتر و ? به معنای دقیقا یک کاراکتر می‌باشد.

جستجو کردن فایل moammaye_hasti.mp3 در دایرکتوری خانگی (و زیر دایرکتوری‌های آن)

Bash
$ find ~ -iname "moammaye_hasti.mp3"

برای اینکه جستجو، هم فایل‌های با حروف کوچک و هم فایل‌های با حروف بزرگ را شامل شود از سوییچ iname- استفاده می‌کنیم. اگر از اسم فایل اطمینان دارید می‌توانید نام را دقیقا مانند نام فایل بنویسید و از سوییچ name- استفاده کنید.

جستجو کردن کلیه فایل‌های mp3 علی

Bash
$ find ~ali -iname "*.mp3"

جستجو کردن کلیه فایل‌های پنهان موجود در دایرکتوری جاری و زیر دایرکتوری‌های آن

Bash
$ find . -name ".*"

می‌دانید که فایل پنهان فایلی است که با دات (.) شروع شود.

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

Bash
$ find ~ -name "???" -d 1

فراموش نکنید چنانچه از * و یا ? استفاده می‌کنید حتما متن را با استفاده از "" و یا ′′ quote کنید و یا اینکه قبل از کاراکتر ویژه * و یا ? علامت \ قرار دهید و یا به عبارت دیگر آن را escape کنید.

ارسال خروجی find به xargs

تا به حال با پیغام arguments too long مواجه شده اید؟ علت این پیغام چیست؟ در واقع پوسته یا shell تا حد معینی می تواند آرگومان‌های خط فرمان را به برنامه فراخوانده شده ارسال کند. وقتی این تعداد از حد معین شده توسط پوسته بیشتر می‌شود، پوسته پیغام arguments too long می‌دهد. برای حل این مشکل و البته برای کاربرد در وضعیت‌های دیگر دستور xargs به کمک می‌آید.

Bash
$ ls | xargs echo

xargs محتوای خوانده شده از ورودی استاندارد را به عنوان آرگومان به دستور خواسته شده می‌فرستند. در دستور فوق ورودی استاندارد به سمت pipe تغییر جهت یافته است و لذا xargs محتوای ارسالی در pipe، که همان خروجی دستور ls است را می‌خواند و آن را به عنوان آرگومان‌های ورودی به دستور echo ارسال می‌کند. xargs محدودیت تعداد آرگومان پوسته را می‌داند و لذا دیگر شاهد پیغام arguments too long نخواهید بود.

برای حذف کلیه فایل‌های mp3 از دایرکتوری جاری به شیوه زیر نیز می‌توان عمل کرد:

Bash
$ ls *.mp3 | xargs rm

دستور ls کلیه فایل‌های خاتمه یافته به پسوند mp3 را لیست می‌کند و آن را به pipe می فرستد. xargs از pipe می‌خواند و محتوای خوانده شده را به عنوان آرگومان‌های دستور rm منظور می‌کند و سپس rm را اجرا می‌کند. اگر لیست فایل‌های mp3 بسیار زیاد باشد در این صورت xargs یکبار دستور rm را با تعداد کافی آرگومان خوانده شده از پایپ اجرا می‌کند و سپس دوباره اقدام به اجرای دستور rm با آرگومان‌های جدید می‌نماید. این عمل تا زمانی که pipe خالی شود ادامه می‌یابد.

دستور بالا را می‌توان با استفاده از find نوشت. توجه کنید چون find جستجو را به صورت تو در تو انجام می‌دهد برای پیاده سازی دقیق دستور بالا باید عمق جستجو را ۱ بگذاریم.

Bash
$ 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 تغییر می‌دهد.

دو دستور زیر و خروجی‌های آن‌ها را ملاحظه بفرمایید.

Bash
$  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

لیست کلیه فایل‌های معمولی در دایرکتوری جاری و لیست کامل اطلاعات آن

Bash
$ find . -type f -d 1 | xargs ls -l

لیست کلیه لینک‌ها در دایرکتوری خانگی (و زیر دایرکتوری‌های آن)

Bash
$ find ~ -type l

لینک‌های موجود در دایرکتوری خانگی به کجا اشاره می کنند؟

Bash
$ 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 تعداد ۵۱۲ بایت می‌باشد.

Bash
$ 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 تعداد ۳ بلاک است. این موضوع را با دستور زیر تست می‌کنیم.

Bash
$ 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 که سایز آنها بیشتر از ۶۰۰ مگا بایت است:

Bash
$ find ~ -type f -iname "*.mp4" -size +600M

لیست فایل‌های jpg که بین ۴۰۰ کیلو بایت تا ۵ مگابایت هستند:

Bash
$ find ~ -type f -iname "*.jpg" -size +400k -size -5M

دستور بالا نشان می‌دهد زمانی که دو یا چند شرط وجود داشته باشد تمامی شرط‌ها می‌بایست true باشند یا به عبارت دیگر شرط‌ها با هم AND می‌شوند.

جستجو بر مبنای سطح دسترسی (permission) فایل

سوییچ perm- برای یافتن فایل با سطوح دسترسی مشخص استفاده می‌شود. عدد قرار گرفته در جلو سوییچ می‌بایست عددی در مبنای ۸ باشد.

فایل‌های دارای اجازه دسترسی ۷۷۷ را نمایش بده.

Bash
$ find ~ -perm 777

فایل‌های دارای اجازه دسترسی ۷۵۵ را نمایش بده.

Bash
$ find ~ -perm 755

بعضی اوقات نیازی به دانستن اجازه دسترسی کامل فایل ندارید و فقط یک مجوز برای شما مهم است. مثلا می‌خواهید بدانید گروه در کدام فایل‌ها اجازه نوشتن دارد. برای این موارد سریعا ترکیب rwx rwx rwx را برای فایل مورد نظر تشکیل دهید. بدیهی است که rwx ها به ترتیب از چپ به راست مجوزهای صاحب فایل، گروه و دیگران هستند. زیر مجوزهایی که برای شما اهمیتی ندارند صفر بگذارید و مجوزهایی که لازم است داشته باشند را یک قرار دهید. عدد حاصله را در مبنای هشت بنویسید و با یک علامت - پیش از آن، جلوی سوییچ perm- قرار دهید.

علامت - پیش از عدد permission می‌گوید که اجازه دسترسی واقعی فایل را با عدد جلوی permission به صورت بیتی AND کن و اگر حاصل درست بود فایل را نمایش بده (یعنی آن فایل مجوزی که برای شما مهم بوده است را دارد.)

کدام فایل‌ها مجوز نوشتن توسط گروه را دارند؟
rwx rwx rwx
000 010 000
عدد هشت بیتی حاصل 020 می‌باشد. از این عدد به صورت زیر استفاده می‌کنیم.

Bash
$ find ~ -perm -020

لیست کامل فایل‌های اجرایی را نمایش بده.
rwx rwx rwx
001 000 000
عدد هشت بیتی حاصل 001 می‌باشد.

Bash
$ 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 می‌باشد.

Bash
$ 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. چنانچه نام فایل، صاحب فایل، گروه و یا تعداد لینک‌های داده شده به فایل و ... تغییر کند بدون اینکه محتوای فایل مورد ویرایش قرار گیرد این تاریخ، زمانی جلوتر از زمان آخرین ویرایش فایل خواهد داشت.

فایل‌هایی که ۷ روز پیش ویرایش شده‌اند را نمایش بده.

Bash
$ find ~ -mtime 7

همین مثال می‌تواند به صورت زیر با استفاده از علامت های + و - نیز نوشته شود.

Bash
$ find ~ -mtime +6 -mtime -7

یعنی زمان ویرایش فایل بیشتر از ۶ روز و کمتر از 7 روز پیش باشد. علامت + شامل همان عدد نمی شود ولی علامت - خود عدد را نیز شامل می‌شود.

فایل‌هایی که بیشتر از ۳۰ روز است که از آنها استفاده نکرده‌ام را نمایش بده.

Bash
$ find ~ -atime +30 -type f

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

Bash
$ (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

کاربرد این سوییچ‌ها دقیقا مانند سوییچ‌های بخش قبل هستند با این تفاوت که همه چیز در اینجا معنای دقیقه می‌دهد.

فایل‌هایی که کمتر از ۶۰ دقیقه قبل ویرایش شده‌اند را نمایش دهید.

Bash
$ find . -type f -mmin -60

فایل‌هایی که کمتر از ۴۰ دقیقه پیش آن‌ها را مشاهده کرده‌ام را نمایش دهید.

Bash
$ find . -type f -amin -40

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

اگر می‌خواهید متوجه شوید زمان آخرین ویرایش چه فایل‌هایی از فایل داده شده کمتر است از سوییچ newer- استفاده کنید.

چه فایل‌هایی از فایل tmp.sh جدیدتر می‌باشند؟

Bash
$ 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/ مشاهده کنید.

Bash
$ cat /etc/passwd | grep ^mohsen
 
mohsen:*:1001:1001:Mohsen Safari:/home/mohsen:/usr/local/bin/bash

مثال بالا خط مربوط به کاربر mohsen در فایل etc/passwd/ را نشان می‌دهد که دارای شماره کاربری ۱۰۰۱ می‌باشد.

از سوییچ group- برای جستجوی فایل‌ها بر مبنای نام گروه و یا شماره‌ی یکتای گروه استفاده می‌شود. شماره یکتای هر گروه را می‌توانید در فایل etc/group/ مشاهده کنید.

Bash
$ cat /etc/group | grep ^mohsen 
 
mohsen:*:1001:

در مثال بالا مشاهده می‌کنید که گروه mohsen دارای شماره یکتای ۱۰۰۱ می‌باشد.

کلیه فایل‌هایی که SGID آن ها به wheel ست شده است را پیدا کنید.

Bash
$ find ~ -group wheel -perm -2000

جستجو بر مبنای i-number

تا به حال دستور ls -li را اجرا کرده‌اید؟ نمونه خروجی این دستور را ببینید:

Bash
$ 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 بیابید.

Bash
$ 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- برای یافتن فایل‌های خالی استفاده می‌شود.

Bash
$ >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- برای یافتن دایرکتوری‌های خالی هم می‌توان استفاده کرد.

Bash
$ 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 دایرکتوری جاری و زیردایرکتوری‌های آن را حذف کنید. لطفا قبل از حذف از من سوال کنید.

Bash
$ find . -iname "*.mp3" -ok rm {} \;

دستور فوق فایل‌های mp3 را یافته و بعد از پرسیدن اینکه آیا دستور اجرا شود یا خیر، در صورت موافقت، دستور rm را روی فایل مورد نظر ({}) اجرا می‌کند. ok- به ازای هر نتیجه یکبار از شما می‌پرسد که آیا دستور را اجرا کند یا خیر. بنابر این شما می‌توانید دستور را روی بعضی از فایل‌ها اجرا کنید و روی بعضی فایل‌ها اجرا نکنید.

از کلیه فایل‌های txt در دایرکتوری فعلی backup بگیرید.

Bash
$ find . -d 1 -iname "*.txt" -exec mv {} {}.bak \;

متاسفانه در اثر بی‌دقتی فایلی به صورت زیر ایجاد شده است که نام آن حاوی تعداد زیادی space است. چه طور می‌توانم آنرا حذف کنم.

Bash
$ ls -li
12039479 -rw-r--r--  1 mohsen  wheel  0 Apr  7 16:02 o      o

ساده‌ترین راه استفاده از دستور find به همراه سوییچ‌های inum- و exec- است.

Bash
$ find . -inum 1203979 -exec rm {} \;

شیوه بالا برای انجام هرگونه عملیات روی فایل‌هایی که دارای کاراکترهای ویژه هستند و یا اینکه نامشان در ترمینال به درستی نمایش داده نمی‌شود مناسب است.

مجوز کلیه فایل‌های داخل دایرکتوری جاری که با عدد شروع می‌شوند را به ۷۵۵ تغییر دهید.

Bash
$ find . -d 1 -name "[0-9]*" -type f -exec chmod 755 {} \;

استفاده از AND و OR و NOT

به صورت پیش فرض کلیه شرط‌های موجود در دستور find با هم AND می‌شوند ولی ما می‌توانیم با استفاده از چند سوییچ و عملگر ! روند پیش فرض find را تغییر دهیم.

عملگر ! قبل از شرط به معنای نقیض شرط مشخص شده می‌باشد.

فایل‌هایی که بزرگتر از ۳۴ کاراکتر نیستند را نمایش بدهید.

Bash
$ find . -d 1 -size -34c
$ find . -d 1 ! -size +34c

دو دستور فوق تاحدودی معادل یکدیگرند. دستور اول می‌گوید سایز فایل کمتر از ۳۴ کاراکتر و دستور دوم می‌گوید سایز فایل بیشتر از ۳۴ کاراکتر نباشد ولی دستور اول فایل‌های ۳۴ کاراکتری را نشان نمی‌دهد ولی دستور دوم نشان می‌دهد.

سوییچ a- به معنای AND و سوییچ o- به معنای OR می‌باشد . شرط‌ها را می‌توانیم با پرانتز گروه‌بندی کنیم. فراموش نکنید به علت اینکه پرانتز برای پوسته معنا دارد آنرا حتما با \ (بک اسلش) escape کنید.

فایل‌هایی که در اسمشان حسن یا حسین می‌باشد را پیدا کنید.

Bash
$ find . \( -iname "*hassan*" -o -iname "*hossein*" \)

دستور فوق می‌تواند به صورت زیر نیز نوشته شود.

Bash
$ find . -iname "*hassan*" -print -o -iname "*hossein*" -print

فایل‌هایی که دیگران اجازه هیچ گونه دسترسی به آن‌ها را ندارند پیدا کنید.

Bash
$ 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

دستور فوق می‌تواند به صورت زیر نیز نوشته شود:

Bash
$ 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

Bash
$ find ~ -type f -iname "moammaye_hasti.mp4"

یافتن ویدیوهای حجیم با حجم بالای ۶۰۰ مگا بایت

Bash
$ find ~ -type f -size +600M

پیدا کردن mp3 هایی که ماه گذشته ریخته بودم توی کامپیوتر. فکر می‌کنم بین ۳۰ تا ۳۵ روز گذشته بود؟!

Bash
$ find ~ -type f -iname "*.mp3" -ctime +29 -ctime -35

حذف کردن عکس‌ها. عکسهام همه پسوند jpg دارند. اگر هم نداشته باشند راحتترم که چند بار دستور find رو برای حذف پسوندهای مختلف صدا بزنم.

Bash
$ find ~/doc/BBAAB‌‌B -type f -iname "*.jpg" -exec rm {} \;

لیست کل فایل‌های دایرکتوری خانه و زیر دایرکتوری‌های آن. جایی که ls به راحتی کمک نمی کنه!

Bash
$ find ~ -type f

فایل‌های رضا را به محسن تغییر مالکیت بده.

Bash
$ find ~ -user reza -ok chown mohsen {} \;

دستور بالا به شرطی اجرا خواهد شد که مجوزهای لازم را داشته باشید.

نظر شما



 
 
 
لینک‌های مفید