لینوکس

آموزش استفاده از find و locate برای جستجوی فایل‌ها در لینوکس

مقدمه

لینوکس چندین ابزار برای پیدا کردن فایل‌ها در اختیارتان می‌گذارد و هر کدام مشکلی متفاوت را حل می‌کنند. دستور find به‌صورت بلادرنگ (Real-Time) سیستم فایل را پیمایش می‌کند و کنترل دقیقی روی مواردی که مطابقت پیدا می‌کنند و کاری که با نتایج انجام می‌دهید در اختیارتان می‌گذارد. دستور locate یک ایندکس از پیش ساخته‌شده را جستجو می‌کند و به همین دلیل وقتی به یک جستجوی سریع برای یافتن مسیر نیاز دارید و لازم نیست نتایج، تغییرات چند ثانیه اخیر سیستم فایل را منعکس کنند، گزینه سریع‌تری است. whereis و which ابزارهایی با دامنه محدودتر هستند که روی باینری دستورات و مکان صفحات راهنمای man تمرکز دارند و وقتی مفیدند که بخواهید مطمئن شوید شل شما کدام نسخه از یک برنامه را اجرا می‌کند.

دانستن اینکه باید سراغ کدام ابزار بروید، زمان شما را حفظ می‌کند. اجرای find / برای پیدا کردن یک فایل پیکربندی که همین حالا نصب کرده‌اید، از اجرای locate روی یک ایندکس به‌روز کندتر است. برعکس، استفاده از locate در یک کانتینر داکری که هرگز updatedb در آن اجرا نشده، هیچ نتیجه‌ای برنمی‌گرداند. انتخاب درست به این بستگی دارد که آیا به دقت بلادرنگ نیاز دارید، دامنه جستجو چقدر بزرگ است و آیا قصد دارید روی نتایج عملیاتی انجام دهید یا نه.

این آموزش هر ابزار را از کاربرد پایه تا الگوهای عملی مدیریتی پوشش می‌دهد: فیلتر کردن بر اساس نام، نوع، حجم، مالکیت، مجوزها و زمان تغییر با find؛ مدیریت ایندکس locate با updatedb؛ اجرای عملیات انبوه با -exec و xargs؛ جستجو در محتوای فایل‌ها با grep؛ و حذف دایرکتوری‌ها از پیمایش با -prune.

نکات کلیدی

  • برای جستجوی بلادرنگ سیستم فایل با فیلترهایی مانند نام، مالکیت، مجوزها، حجم، زمان و عمق، از find استفاده کنید.
  • برای جستجوی سریع مسیرها از روی ایندکس از locate استفاده کنید و هر وقت فایل‌های اخیر پیدا نشدند، updatedb را اجرا کنید.
  • برای پیدا کردن باینری‌ها و مسیر دستورات از whereis و which استفاده کنید، نه برای جستجوی عمومی فایل‌ها.
  • برای اجرای عملیات انبوه روی نتایج از -exec و xargs استفاده کنید و برای کارایی بهتر، اجرای دسته‌ای را ترجیح دهید.

انتخاب بین find، locate، whereis و which

وقتی دقت و نتایج بلادرنگ اهمیت دارند از find استفاده کنید و وقتی سرعت از تازگی لحظه‌ای نتایج مهم‌تر است از locate. whereis و which مسئله‌ای محدودتر را حل می‌کنند: پیدا کردن دستورات. از سوی دیگر، fd یک جایگزین مدرن برای find است که به‌صورت پیش‌فرض روی دبیان و اوبونتو نصب نیست.

ابزارسرعتنتایج بلادرنگجستجو بر اساسنیاز به نصب
findروی درخت‌های بزرگ کندتربلهنام، نوع، مالک، مجوزها، حجم، زمان، عمق و موارد دیگرخیر
locateبسیار سریعخیر؛ به عمر ایندکس وابسته استزیررشته‌های مسیر در ایندکس، نام فایل (-b)معمولاً بله (mlocate یا plocate)
fdسریعبلهتطبیق نام و الگو با پیش‌فرض‌های ساده‌تربله؛ روی دبیان و اوبونتو: apt install fd-find
whereisسریعبلهمکان باینری، سورس و صفحات راهنماخیر
whichسریعبلهاولین فایل اجرایی مطابق در $PATHخیر

برای کارهای مدیریتی روزمره، برای فیلترهای دقیق از find شروع کنید، برای جستجوی سریع و گسترده از locate استفاده کنید و هنگام بررسی باینری دستورات به whereis یا which مراجعه کنید. همچنین می‌توانید ابزارهای لینوکسی مرتبط را در راهنمای دستورات لینوکس پارمین کلود مرور کنید.

پیش‌نیازها

برای دنبال کردن این آموزش به یک سیستم مبتنی بر لینوکس نیاز دارید؛ چه یک ماشین محلی و چه یک سرور ریموت که با SSH وارد آن می‌شوید. مثال‌های این آموزش روی یک سرور لینوکسی با اوبونتو 24.04 LTS اعتبارسنجی شده‌اند و روی اوبونتو 20.04 و 22.04 و نسخه‌های جدیدتر و همچنین بسیاری از توزیع‌های دیگر لینوکس هم قابل استفاده هستند.

اگر قصد دارید از یک سرور ریموت استفاده کنید، ابتدا راهنمای راه‌اندازی اولیه سرور اوبونتو در پارمین کلود را کامل کنید. این راهنما یک کاربر غیر root با دسترسی sudo و یک فایروال آماده می‌کند تا بتوانید دستورات مدیریتی را با اطمینان اجرا کنید.

نکته: برای نمایش نحوه کار دستورات find و locate، دستورات نمونه این آموزش فایل‌های موجود در مسیر / یعنی دایرکتوری ریشه (root) را جستجو می‌کنند. به همین دلیل اگر با کاربر غیر root وارد ترمینال شده باشید، ممکن است خروجی برخی دستورات شامل پیام Permission denied باشد.

این وضعیت کاملاً طبیعی است؛ چون در حال جستجو در دایرکتوری‌هایی هستید که معمولاً کاربران عادی به آن‌ها دسترسی ندارند. با این حال، این دستورات نمونه همچنان کار می‌کنند و برای درک نحوه عملکرد این برنامه‌ها مفید هستند.

استفاده از دستور locate

از locate استفاده کنید وقتی به جستجوی سریع مسیر در کل سیستم نیاز دارید و می‌توانید نتایج یک ایندکسِ کمی قدیمی را بپذیرید.

برای نصب locate روی دبیان و اوبونتو، ابتدا متادیتای پکیج‌ها را به‌روز کنید و سپس plocate را نصب کنید که در نسخه‌های جدید اوبونتو پیش‌فرض است:

sudo apt update
sudo apt install plocate

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

sudo apt install mlocate

روی راکی لینوکس (Rocky Linux)، سنت‌او‌اس (CentOS) و سایر توزیع‌های مبتنی بر Red Hat، نصب را با dnf انجام دهید:

sudo dnf install mlocate

locate از find سریع‌تر است، چون به‌جای پیمایش بلادرنگ سیستم فایل، از یک دیتابیس می‌خواند. شکل کلی دستور به این صورت است:

locate query

این دستور مسیرهایی را برمی‌گرداند که عبارت query در هر جای مسیر کامل آن‌ها آمده باشد. برای تطبیق فقط با نام خود فایل (basename)، سوییچ -b را اضافه کنید:

locate -b query

برای برگرداندن فقط مسیرهایی که واقعاً وجود دارند و رد شدن از ورودی‌های منقضی ایندکس، از -e استفاده کنید:

locate -e query

برای مشاهده آمار ایندکس:

locate -S
Database /var/lib/plocate/plocate.db:
    21015 directories
    136787 files
    7727763 bytes in file names
    3264413 bytes used to store database

نحوه کار updatedb

دستور updatedb ایندکس locate را با پیمایش فایل‌سیستم‌های مونت‌شده و ثبت مسیرها در فایل دیتابیس می‌سازد. بیشتر سیستم‌ها این کار را روزانه انجام می‌دهند؛ اغلب از طریق /etc/cron.daily/mlocate یا /etc/cron.daily/plocate، در حالی که سیستم‌های جدیدتر ممکن است از تایمر systemd استفاده کنند که توسط پکیج plocate یا mlocate مدیریت می‌شود.

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

sudo updatedb

رفتار updatedb با فایل /etc/updatedb.conf کنترل می‌شود؛ از جمله مسیرها و فایل‌سیستم‌هایی که از ایندکس حذف می‌شوند (prune):

PRUNE_BIND_MOUNTS="yes"
PRUNEPATHS="/tmp /var/spool /media /var/lib/os-prober /var/lib/docker"
PRUNEFS="NFS nfs nfs4 rpc_pipefs afs binfmt_misc proc smbfs autofs iso9660 devpts cgroup2"

نکته: مقادیر بالا صرفاً نمونه هستند. سیستم شما ممکن است مسیرهای بیشتری در PRUNEPATHS و انواع فایل‌سیستم بیشتری در PRUNEFS داشته باشد. فقط مقادیری را ویرایش کنید که با محیط شما مرتبطند.

برای خارج کردن یک دایرکتوری از ایندکس‌شدن، آن را به PRUNEPATHS اضافه کنید و دوباره sudo updatedb را اجرا کنید.

برای اطمینان از حذف شدن دایرکتوری، برای مسیری داخل آن locate را اجرا کنید و مطمئن شوید هیچ نتیجه‌ای برنمی‌گردد:

locate excluded_directory_path

اگر همچنان نتیجه‌ای نمایش داده شد، بررسی کنید که فایل /etc/updatedb.conf را ذخیره کرده باشید و دستور updatedb بدون خطا کامل شده باشد.

نکته: locate فقط آخرین اجرای موفق updatedb را نشان می‌دهد. فایل‌هایی که بعد از آن اجرا ایجاد، حذف یا جابه‌جا شده‌اند، تا به‌روزرسانی بعدی ایندکس به‌درستی نمایش داده نمی‌شوند.

هشدار: در کانتینرهای داکر و فایل‌سیستم‌های موقت دیگر، ممکن است دیتابیس‌های locate وجود نداشته باشند، قدیمی باشند یا با بازسازی کانتینر ریست شوند. برای بررسی‌های قطعاً بلادرنگ در محیط‌های کوتاه‌عمر از find استفاده کنید.

اگر می‌خواهید زمان‌بندی به‌روزرسانی را خودتان تعیین کنید، راهنمای زمان‌بندی وظایف روتین با cron و anacron در پارمین کلود را مطالعه کنید.

استفاده از دستور find

از find استفاده کنید وقتی به فیلتر کردن دقیق و بلادرنگ روی دایرکتوری‌ها نیاز دارید.

جستجو بر اساس نام

جستجو بر اساس نام دقیق فایل، با حساسیت به بزرگی و کوچکی حروف:

find -name "query"

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

برای جستجوی بدون حساسیت به بزرگی و کوچکی حروف:

find -iname "query"

برای معکوس کردن جستجو:

find -not -name "query_to_avoid"

همچنین می‌توانید با ! معکوس کنید؛ آن را به‌صورت \! می‌نویسند تا شل قبل از find آن را تفسیر نکند:

find \! -name "query_to_avoid"

جستجو بر اساس نوع

از -type استفاده کنید وقتی می‌خواهید نتایج را به نوع خاصی از اشیای سیستم فایل محدود کنید؛ مثلاً فقط فایل‌های معمولی یا فقط دایرکتوری‌ها، فارغ از نام آن‌ها.

فیلتر کردن بر اساس نوع فایل:

find -type type_descriptor -name query

توصیف‌گرهای (Descriptor) رایج:

  • f: فایل معمولی
  • d: دایرکتوری
  • l: لینک سمبولیک (Symbolic Link)
  • c: دستگاه کاراکتری (Character Device)
  • b: دستگاه بلوکی (Block Device)

پیدا کردن دستگاه‌های کاراکتری در /dev:

find /dev -type c
/dev/vcsa5
/dev/vcsu5
/dev/vcs5
/dev/vcsa4
/dev/vcsu4
/dev/vcs4
/dev/vcsa3
/dev/vcsu3
/dev/vcs3
/dev/vcsa2
/dev/vcsu2
/dev/vcs2
. . .

جستجوی فایل‌های .conf در /usr:

find /usr -type f -name "*.conf"
/usr/src/linux-headers-6.8.0-45-generic/include/config/auto.conf
/usr/src/linux-headers-6.8.0-45-generic/include/config/tristate.conf
/usr/src/linux-headers-6.8.0-40-generic/include/config/auto.conf
/usr/src/linux-headers-6.8.0-40-generic/include/config/tristate.conf
/usr/share/adduser/adduser.conf
/usr/share/ufw/ufw.conf
/usr/share/popularity-contest/default.conf
/usr/share/byobu/keybindings/tmux-screen-keys.conf
/usr/share/libc-bin/nsswitch.conf
/usr/share/rsyslog/50-default.conf
. . .

نکته: مثال قبلی دو عبارت جستجوی find را با هم ترکیب می‌کند؛ یعنی -type f و -name "*.conf". برای اینکه فایلی برگردانده شود، باید هر دو شرط را برآورده کند.

می‌توانید عبارت‌ها را با جدا کردن آن‌ها به‌وسیله گزینه -and به این شکل ترکیب کنید، اما همان‌طور که این مثال نشان می‌دهد، هر وقت دو عبارت را کنار هم قرار دهید، -and به‌صورت ضمنی در نظر گرفته می‌شود. همچنین می‌توانید نتایجی را برگردانید که یکی از دو عبارت را برآورده کنند؛ کافی است آن‌ها را با -or از هم جدا کنید:

find -name query_1 -or -name query_2

این مثال هر فایلی را پیدا می‌کند که نامش با query_1 یا query_2 مطابقت داشته باشد.

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

از -size، -mtime، -atime، -ctime و فلگ‌های مرتبط برای محدود کردن سریع نتایج استفاده کنید.

حجم

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

  • c: بایت
  • k: کیلوبایت
  • M: مگابایت
  • G: گیگابایت
  • b: بلوک‌های ۵۱۲ بایتی

پیدا کردن فایل‌های دقیقاً ۵۰ بایتی:

find /usr -size 50c

پیدا کردن فایل‌های کمتر از ۵۰ بایت:

find /usr -size -50c

پیدا کردن فایل‌های بزرگ‌تر از ۷۰۰ مگابایت:

find /usr -size +700M

زمان

از -mtime، -atime و -ctime برای فیلتر کردن فایل‌ها بر اساس زمان آخرین تغییر، آخرین دسترسی یا آخرین تغییر متادیتای آن‌ها استفاده کنید. عدد صحیح مثبت یعنی دقیقاً N روز پیش، عدد منفی (-N) یعنی در N روز گذشته و عدد مثبت با علامت + (+N) یعنی بیش از N روز پیش.

  • زمان دسترسی (-atime): آخرین باری که از فایل خوانده یا در آن نوشته شد.
  • زمان تغییر (-mtime): آخرین باری که محتوای فایل تغییر کرد.
  • زمان تغییر inode (-ctime): آخرین باری که متادیتای inode تغییر کرد.

برای پیدا کردن فایل‌هایی که در روز گذشته تغییر کرده‌اند، از -1 به معنای کمتر از یک روز پیش استفاده کنید:

find /usr -mtime -1

استفاده از 1 بدون علامت، فایل‌هایی را تطبیق می‌دهد که دقیقاً یک روز پیش تغییر کرده‌اند که به‌ندرت همان چیزی است که می‌خواهید. استفاده از -1 هر چیزی را در ۲۴ ساعت گذشته شامل می‌شود.

برای پیدا کردن فایل‌هایی که در روز گذشته به آن‌ها دسترسی داشته‌اید:

find /usr -atime -1

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

find /usr -ctime +3

این گزینه‌ها پارامترهای همراهی هم دارند که می‌توانید به‌جای روز، دقیقه را مشخص کنید:

find /usr -mmin -1

این دستور فایل‌هایی را برمی‌گرداند که در دقیقه گذشته تغییر کرده‌اند.

از -newer برای مقایسه با یک فایل مرجع استفاده کنید:

find / -newer reference_file

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

جستجو بر اساس مالک و مجوزها

جستجوی فایل‌ها بر اساس مالک با -user و بر اساس گروه با -group:

find /var -user syslog

به‌طور مشابه، می‌توانید فایل‌های دایرکتوری /etc را که متعلق به گروه shadow هستند با این دستور مشخص کنید:

find /etc -group shadow

همچنین می‌توانید بر اساس مجوزها جستجو کنید که هنگام ممیزی کنترل دسترسی (Audit) مفید است. برای مرور عمیق‌تر این موضوع، راهنمای مقدمه‌ای بر مجوزهای لینوکس در پارمین کلود را بخوانید.

نکته: جستجو از مسیر / کل فایل‌سیستم را پیمایش می‌کند و ممکن است برای کاربران غیر root خروجی Permission denied قابل توجهی تولید کند. تا جای ممکن دامنه جستجو را به یک دایرکتوری مشخص مانند /home یا /var محدود کنید.

تطبیق یک حالت (mode) دقیق:

find / -perm 644

این دستور فایل‌هایی را با دقیقاً همان مجوزهای مشخص‌شده تطبیق می‌دهد.

تطبیق فایل‌هایی که حداقل این مجوزها را دارند:

find / -perm -644

این دستور هر فایلی را که مجوزهای اضافه‌تری داشته باشد تطبیق می‌دهد. مثلاً فایلی با مجوز 744 در این حالت هم تطبیق داده می‌شود.

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

از -empty برای پیدا کردن فایل‌ها یا دایرکتوری‌هایی که هیچ داده یا محتوایی ندارند استفاده کنید. این کار برای پاک‌سازی فایل‌های جای‌نگهدار (placeholder) و دایرکتوری‌های خالی که توسط نصب‌کننده‌ها یا ابزارهای بیلد باقی مانده‌اند، مفید است.

پیدا کردن فایل‌های خالی:

find /tmp -type f -empty

پیدا کردن دایرکتوری‌های خالی:

find /tmp -type d -empty

اجرای عملیات روی نتایج جستجو با -exec و xargs

از -exec برای اجرای مستقیم عملیات روی هر نتیجه داخل خود find استفاده کنید و از xargs وقتی می‌خواهید دستورات را به‌صورت دسته‌ای یا موازی اجرا کنید.

اجرای یک دستور برای هر فایل مطابقت‌یافته:

find find_parameters -exec command_and_options {} \;

توکن {} با هر مسیر مطابقت‌یافته جایگزین می‌شود و \; دستور را پایان می‌دهد.

مثلاً از داخل /tmp/test، حالت (mode) فایل‌های مطابقت‌یافته را به‌روز کنید:

find . -type f -perm 644 -exec chmod 664 {} \;

تغییر حالت دایرکتوری‌های مطابقت‌یافته:

find . -type d -perm 755 -exec chmod 700 {} \;

حذف انبوه و اجرای دسته‌ای

حذف فایل‌های موقت .bak:

find /tmp/test -type f -name "*.bak" -exec rm {} \;

اگر هیچ فایل مطابقی وجود نداشته باشد، دستور بی‌صدا اجرا می‌شود و به پرامپت برمی‌گردد.

وقتی از -exec ... {} \; استفاده می‌کنید، find برای هر مورد یک زیرپروسه (subprocess) راه می‌اندازد که روی مجموعه نتایج بزرگ، سربار ایجاد می‌کند. حالت دسته‌ای با -exec ... {} + مسیرهای زیادی را یک‌جا پاس می‌دهد؛ این کار تعداد ساخت پروسه را کاهش می‌دهد و معمولاً سریع‌تر اجرا می‌شود:

find /tmp/test -type f -name "*.log" -exec rm {} +

رفتار بی‌صدای مشابهی وقتی از {} با + استفاده می‌شود و هیچ موردی پیدا نمی‌شود هم برقرار است.

هشدار: دستورات حذف، مخرب هستند. ابتدا همان کوئری find را بدون rm -exec تست کنید، یا برای یک اجرای آزمایشی (Dry Run) به‌جای rm از ls -l استفاده کنید.

استفاده از xargs برای زنجیره‌سازی و موازی‌سازی

xargs لیست مسیرها را از ورودی استاندارد می‌خواند و خطوط فرمان را به‌شکل بهینه می‌سازد. این ابزار برای اجرای موازی، دسته‌بندی صریح یا دستوراتی که مستقیماً به find متصل نیستند، کاربردی است.

شمارش فایل‌های مطابقت‌یافته و سپس فشرده‌سازی موازی آن‌ها با ۴ ورکر:

find /var/log -type f -name "*.log" | wc -l
42
find /var/log -type f -name "*.log" -print0 | xargs -0 -n 10 -P 4 gzip

اگر فایل‌ها با موفقیت فشرده شوند، دستور بی‌صدا اجرا می‌شود و به پرامپت برمی‌گردد.

در عمل، وقتی دسته‌بندی ساده و امن را مستقیماً در خود find می‌خواهید، از -exec ... {} + استفاده کنید. از xargs وقتی استفاده کنید که به گزینه‌هایی مانند ورکرهای موازی (-P)، اندازه دسته ثابت (-n) یا زنجیره‌سازی پیچیده‌تر دستورات نیاز دارید.

جستجو در محتوای فایل با find و grep

از find برای انتخاب فایل‌ها بر اساس نام یا نوع استفاده کنید، سپس نتایج را به grep بدهید تا درون آن‌ها جستجو شود.

جستجوی یک رشته خاص در همه فایل‌های .conf داخل /etc، همراه با چاپ نام فایل کنار هر مورد:

find /etc -type f -name "*.conf" -exec grep -H "PermitRootLogin" {} \;
/etc/ssh/sshd_config:PermitRootLogin no

فلگ -H به grep می‌گوید نام فایل را در خروجی بگنجاند. بدون آن فقط خط مطابقت‌یافته را می‌بینید و وقتی چند فایل مطابقت دارند، نمی‌توان تشخیص داد هر خط متعلق به کدام فایل است.

برای برگرداندن فقط نام فایل‌هایی که مورد مطابقت دارند، بدون چاپ خودِ خطوط مطابقت‌یافته، از -l استفاده کنید:

find /etc -type f -name "*.conf" -exec grep -l "PermitRootLogin" {} \;
/etc/ssh/sshd_config

برای نام فایل‌هایی که فاصله یا کاراکترهای خاص دارند، از -print0 به همراه xargs -0 استفاده کنید تا به‌صورت امن مدیریت شوند:

find /etc -type f -name "*.conf" -print0 | xargs -0 grep -H "127.0.0.1"

روی درخت‌های دایرکتوری بزرگ، روش xargs از -exec grep {} \; سریع‌تر است؛ چون به‌جای ساخت یک پروسه برای هر فایل، چندین فایل را به یک فراخوانی grep پاس می‌دهد.

استفاده از whereis و which برای پیدا کردن باینری و مسیر

از whereis و which برای پیدا کردن مسیرهای مرتبط با دستورات استفاده کنید، نه برای فایل‌های دلخواه.

whereis مسیرهای باینری، سورس و صفحه راهنما را در صورت وجود برمی‌گرداند:

whereis ls
ls: /usr/bin/ls /usr/share/man/man1/ls.1.gz

می‌توانید چند دستور را هم‌زمان کوئری کنید:

whereis find grep ssh
find: /usr/bin/find /usr/share/man/man1/find.1.gz
grep: /usr/bin/grep /usr/share/man/man1/grep.1.gz
ssh: /usr/bin/ssh /usr/share/man/man1/ssh.1.gz

which اولین مورد قابل اجرا در مسیر ($PATH) فعلی را برمی‌گرداند:

which python3
/usr/bin/python3

از which استفاده کنید وقتی می‌خواهید بررسی کنید شل شما کدام باینری را فراخوانی خواهد کرد؛ مخصوصاً وقتی چند نسخه از یک ابزار نصب است. از whereis وقتی استفاده کنید که به مکان صفحات راهنما هم نیاز دارید. برای جستجوی عمومی سیستم فایل از find استفاده کنید، چون whereis و which فیلترهای مالکیت، مجوز، حجم، زمان یا عمق را اعمال نمی‌کنند.

برای محدود کردن خروجی whereis به نوع خاصی از مکان، از فلگ‌های -b، -m یا -s استفاده کنید:

whereis -b find
find: /usr/bin/find

-b فقط مسیر باینری را برمی‌گرداند، -m فقط مسیر صفحه راهنما را برمی‌گرداند و -s هم فقط مسیر سورس را در صورت وجود برمی‌گرداند.

از which برای اطمینان از در دسترس بودن یک دستور و پیدا کردن باینری آن استفاده کنید:

which htop
/usr/bin/htop

اگر دستور نصب است اما which چیزی برنمی‌گرداند، بررسی کنید که دایرکتوری آن در $PATH قرار داشته باشد:

echo $PATH

روی سیستم‌هایی که چند نسخه پایتون دارند، ممکن است which python3 و which python مسیرهای متفاوتی برگردانند. قبل از اجرای اسکریپت‌هایی که به نسخه خاصی وابسته‌اند، با which مطمئن شوید شل شما کدام باینری را اجرا خواهد کرد.

تکنیک‌های پیشرفته find

از گزاره‌های (Predicate) پیشرفته استفاده کنید وقتی که به کنترل دقیق‌تری روی عمق پیمایش نیاز دارید یا می‌خواهید دایرکتوری‌های خاصی را از جستجو حذف کنید.

فیلتر کردن بر اساس عمق

از -maxdepth و -mindepth برای کنترل تعداد سطوح دایرکتوری‌هایی که find در آن‌ها پایین می‌رود استفاده کنید. این کار وقتی مفید است که می‌دانید فایل‌ها در عمق مشخصی قرار دارند و می‌خواهید از پیمایش کل درخت اجتناب کنید.

برای دنبال کردن مثال‌های این بخش، یک ساختار دایرکتوری تستی در /tmp/ بسازید. فایل‌ها و دایرکتوری‌های زیر /tmp/ با ریبوت بعدی حذف می‌شوند؛ پس سیستم شما شلوغ نمی‌شود.

بعد از اجرای دستورات این بخش، دایرکتوری /tmp/ شما شامل سه سطح دایرکتوری با ۱۰ دایرکتوری در سطح اول خواهد بود. هر دایرکتوری، از جمله دایرکتوری موقت، شامل ۱۰ فایل و ۱۰ زیردایرکتوری خواهد بود.

ساختار دایرکتوری نمونه را داخل /tmp/ با دستور زیر بسازید:

mkdir -p /tmp/test/level1dir{1..10}/level2dir{1..10}/level3dir{1..10}

سپس با دستور touch این دایرکتوری‌ها را با چند فایل نمونه پر کنید:

touch /tmp/test/{file{1..10},level1dir{1..10}/{file{1..10},level2dir{1..10}/{file{1..10},level3dir{1..10}/file{1..10}}}}

با آماده شدن این فایل‌ها و دایرکتوری‌ها، وارد دایرکتوری test/ که ساختید شوید:

cd /tmp/test

برای درک پایه‌ای از نحوه بازیابی فایل‌ها توسط find از این ساختار، با یک جستجوی معمولی نام شروع کنید که هر فایلی به نام file1 را پیدا می‌کند:

find -name "file1"
./level1dir7/level2dir8/level3dir9/file1
./level1dir7/level2dir8/level3dir3/file1
./level1dir7/level2dir8/level3dir4/file1
./level1dir7/level2dir8/level3dir1/file1
./level1dir7/level2dir8/level3dir8/file1
./level1dir7/level2dir8/level3dir7/file1
./level1dir7/level2dir8/level3dir2/file1
./level1dir7/level2dir8/level3dir6/file1
./level1dir7/level2dir8/level3dir5/file1
./level1dir7/level2dir8/file1
. . .

نکته: همیشه آرگومان‌های نامی که به -name و -iname می‌دهید را داخل کوتیشن قرار دهید. بدون کوتیشن، ممکن است شل کاراکترهای glob مانند * یا ? را قبل از اینکه find آن‌ها را ببیند توسعه دهد و نتایج غیرمنتظره‌ای بگیرید.

این دستور نتایج زیادی برمی‌گرداند. اگر خروجی را به یک شمارنده پایپ کنید، می‌بینید که در مجموع ۱۱۱۱ نتیجه وجود دارد:

find -name "file1" | wc -l
1111

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

find -maxdepth num -name query

برای پیدا کردن file1 فقط در دایرکتوری‌های level1 و بالاتر، می‌توانید حداکثر عمق را ۲ بگذارید (۱ برای دایرکتوری سطح بالا و ۱ برای دایرکتوری‌های level1):

find -maxdepth 2 -name "file1"
./level1dir7/file1
./level1dir1/file1
./level1dir3/file1
./level1dir8/file1
./level1dir6/file1
./file1
./level1dir2/file1
./level1dir9/file1
./level1dir4/file1
./level1dir5/file1
./level1dir10/file1

این فهرست بسیار قابل مدیریت‌تر است.

همچنین می‌توانید حداقل عمق را تعیین کنید اگر می‌دانید فایل‌های مورد نیازتان در سطوح عمیق‌تری قرار دارند:

find -mindepth num -name query

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

find -mindepth 4 -name "file1"
./level1dir7/level2dir8/level3dir9/file1
./level1dir7/level2dir8/level3dir3/file1
./level1dir7/level2dir8/level3dir4/file1
./level1dir7/level2dir8/level3dir1/file1
./level1dir7/level2dir8/level3dir8/file1
./level1dir7/level2dir8/level3dir7/file1
./level1dir7/level2dir8/level3dir2/file1
. . .

باز هم به‌دلیل ساختار انشعابی دایرکتوری‌ها، تعداد زیادی نتیجه (۱۰۰۰ مورد) برگردانده می‌شود.

می‌توانید پارامترهای حداقل و حداکثر عمق را ترکیب کنید تا روی یک بازه باریک تمرکز کنید:

find -mindepth 2 -maxdepth 3 -name "file1"
./level1dir7/level2dir8/file1
./level1dir7/level2dir5/file1
./level1dir7/level2dir7/file1
./level1dir7/level2dir2/file1
./level1dir7/level2dir10/file1
./level1dir7/level2dir6/file1
./level1dir7/level2dir3/file1
./level1dir7/level2dir4/file1
./level1dir7/file1
. . .

ترکیب این گزینه‌ها نتایج را به‌طور چشمگیری محدود می‌کند و به‌جای ۱۰۰۰ مورد قبلی، فقط ۱۱۰ خط برمی‌گرداند.

حذف دایرکتوری‌ها از پیمایش با -prune

از -prune برای رد شدن از دایرکتوری‌های خاص در حین جستجو استفاده کنید. این کار جلوی پایین رفتن find در دایرکتوری‌هایی مانند .git، node_modules یا مسیرهای vendor را می‌گیرد که در غیر این صورت نویز ایجاد می‌کنند یا جستجو را به‌شدت کند می‌کنند.

جستجوی فایل‌های .js با رد شدن از دایرکتوری node_modules:

find . -type d -name "node_modules" -prune -o -type f -name "*.js" -print

عملگر -o به معنای OR است. دستور find دایرکتوری node_modules را حذف از پیمایش (prune) می‌کند و سپس برای بقیه موارد، فایل‌های .js را چاپ می‌کند. اگر -print در انتها نباشد، find نام خودِ دایرکتوری prune‌شده را هم چاپ می‌کرد.

نکته: -prune دایرکتوری‌ها را حذف نمی‌کند؛ فقط به find می‌گوید در جستجوی فعلی داخل آن‌ها پایین نرود.

سوالات متداول

تفاوت دستورات find و locate در لینوکس چیست؟

دستور find به‌صورت بلادرنگ سیستم فایل را پیمایش می‌کند، پس نتایجش بلافاصله وضعیت فعلی را منعکس می‌کنند. locate یک دیتابیس ایندکس‌شده را جستجو می‌کند که روی سیستم‌های بزرگ بسیار سریع‌تر است. البته locate ممکن است تغییرات خیلی اخیر را تا زمان اجرای updatedb پیدا نکند.

چطور دیتابیس locate را دستی به‌روز کنم؟

دستور sudo updatedb را اجرا کنید تا ایندکس locate در هر زمانی که لازم بود بازسازی شود. این دستور دیتابیس مسیر فایل‌ها را که locate از آن استفاده می‌کند، رفرش می‌کند. اگر مجوزها مانع دسترسی به بعضی مسیرها شوند، آن را با دسترسی مناسب اجرا کنید.

چطور با دستور find بر اساس نام فایل جستجو کنم؟

برای تطبیق حساس به بزرگی و کوچکی حروف از find -name "query" استفاده کنید. برای بی‌توجهی به بزرگی و کوچکی حروف از find -iname "query" استفاده کنید. برای محدود کردن دامنه جستجو، یک دایرکتوری شروع اضافه کنید؛ مثلاً find /etc -name "*.conf".

چطور در محتوای فایل‌ها در لینوکس جستجو کنم؟

دستور find را با grep ترکیب کنید؛ مثلاً find /etc -type f -name "*.conf" -exec grep -H "pattern" {} \;. این دستور ابتدا بر اساس نام فایل فیلتر می‌کند و سپس محتوا را جستجو می‌کند. برای مدیریت امن‌تر کاراکترهای خاص در نام فایل‌ها، از -print0 به همراه xargs -0 استفاده کنید.

فلگ -exec در دستور find چه کاری انجام می‌دهد؟

-exec دستور دیگری را روی هر موردِ برگردانده‌شده توسط find اجرا می‌کند. جای‌نگهدار {} با مسیر مطابقت‌یافته جایگزین می‌شود. از \; برای اجرای یک دستور به ازای هر فایل یا از + برای اجرای دسته‌ای استفاده کنید.

چه زمانی باید به‌جای -exec از xargs استفاده کنم؟

وقتی به دسته‌بندی صریح با -n، موازی‌سازی با -P یا پایپ‌لاین‌های دستوری با ورودی استاندارد نیاز دارید، از xargs استفاده کنید. روی مجموعه نتایج بزرگ اغلب سریع‌تر است؛ چون چندین فایل را در هر فراخوانی گروه می‌کند. برای مدیریت امن فاصله‌ها و کاراکترهای خاص از -print0 و xargs -0 استفاده کنید.

تفاوت whereis و which چیست؟

which اولین فایل اجرایی پیدا شده در $PATH شما را برمی‌گرداند که به تأیید اینکه چه چیزی در شل اجرا می‌شود کمک می‌کند. whereis می‌تواند مکان باینری، سورس و صفحات راهنما را برگرداند. هیچ‌کدام جایگزین find برای جستجوی عمومی فایل نمی‌شوند.

آیا locate داخل کانتینرهای داکر یا فایل‌سیستم‌های موقت کار می‌کند؟

بستگی دارد که آیا در آن محیط اجرایی ایندکسی وجود دارد و به‌روز نگه داشته می‌شود یا نه. بسیاری از کانتینرهای کوتاه‌عمر، دیتابیس locate مفیدی را بین ری‌استارت‌ها نگه نمی‌دارند. در چنین محیط‌هایی برای گرفتن نتایج دقیق، find را ترجیح دهید.

نتیجه‌گیری

از find وقتی نیاز به نتایج فوری و پُر از فیلتر دارید استفاده کنید و از locate وقتی به جستجوهای سریع ایندکس‌شده نیاز دارید. هنگام بررسی مسیرهای اجرایی و مکان صفحات راهنما در فرایندهای عیب‌یابی شل و پکیج‌ها، whereis و which را هم به کار ببرید.

نوشته های مشابه

دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *

دکمه بازگشت به بالا