الأمر find في Linux: البحث عن الملفات بالاسم والحجم والتاريخ، أمثلة
يتجول الأمر find في شجرة المجلدات ويختار الملفات حسب الشروط: find /path -name '*.log' يبحث بالاسم، و-type f للملفات فقط، و-size +100M لما يزيد عن 100 ميغابايت، و-mtime -7 لما عُدّل خلال أسبوع. تُجمع الشروط معاً، ويمكن تنفيذ إجراء على النتائج عبر -exec أو -delete أو تمرير القائمة إلى xargs.
الأمر find يتجول في شجرة المجلدات ويجد الملفات حسب الشروط: الاسم والنوع والحجم وتاريخ التعديل والمالك والصلاحيات. والصيغة العامة هي find [مكان البحث] [الشروط] [الإجراء]. فيما يلي أمثلة find في Linux للمهام الشائعة: العثور على ملف إعدادات، وتنظيف السجلات القديمة، ومعرفة ما يستهلك مساحة القرص.
بنية الأمر find
find /var/log -type f -name '*.log' -mtime +30 -print
نفصّل الأمر على أجزاء:
/var/log— نقطة البداية. يمكن ذكر عدة مجلدات متتالية أو.(المجلد الحالي). وبدون مسار يبحث GNU find في المجلد الحالي.-type f -name '*.log' -mtime +30— الشروط (وتسمى في التوثيق «اختبارات»). وبينها يكون الربط الافتراضي «و» منطقياً.-print— الإجراء: طباعة المسار. ويُضاف تلقائياً إذا لم تُذكر إجراءات أخرى.
يعمل find بشكل تكراري داخل كل المجلدات المتداخلة. وإذا شغّلته كمستخدم عادي على مسارات النظام، فستمتلئ المخرجات بأسطر Permission denied. تخلّص منها بتحويل تيار الأخطاء:
find / -name 'nginx.conf' 2>/dev/null
البحث بالاسم: -name و-iname
يقارن الشرط -name اسم الملف فقط (دون المسار) مع النمط. ويدعم النمط * (أي عدد من الأحرف)، و? (حرف واحد)، و[abc] (أحد الأحرف المذكورة).
# اسم محدد
find /etc -name 'hosts'
# كل ملفات .conf
find /etc -name '*.conf'
# دون مراعاة حالة الأحرف: README.md وreadme.MD وReadme.md
find ~/projects -iname 'readme.md'
# report_1.csv ... report_9.csv
find . -name 'report_?.csv'
ضع النمط دائماً بين علامتي اقتباس. فبدونهما ستوسّع الصدفة *.conf وفق الملفات الموجودة في المجلد الحالي، فيحصل find على قائمة أسماء وليس نمطاً، فتكون النتيجة غير متوقعة أو يفشل الأمر برسالة paths must precede expression.
البحث بالمسار: -path وregex
إذا كان المجلد مهماً وليس الاسم فقط، فاستخدم -path، فهو يقارن النمط مع المسار كاملاً:
# ملفات .js داخل مجلدات src فقط
find . -path '*/src/*' -name '*.js'
وللأنماط المعقدة يوجد -regex (تعبير نمطي على المسار الكامل) و-iregex دون مراعاة الحالة:
find . -regextype posix-extended -regex '.*\.(jpg|jpeg|png)$'
كيف تستثني مجلداً
لكي لا يدخل find مثلاً إلى node_modules أو .git، تُستخدم -prune:
find . -path ./node_modules -prune -o -name '*.js' -print
تُقرأ هكذا: «إذا كان المسار ./node_modules فلا تدخل إليه، وإلا (-o) اطبع ملفات *.js». والخيار -print الصريح في النهاية ضروري، وإلا فسيظهر المجلد المستثنى نفسه في المخرجات. والبديل الأبسط والأبطأ هو -not -path '*/node_modules/*': يمرّ find على المجلد كله، لكنه يصفّي النتيجة فقط.
البحث بالنوع: -type
| القيمة | ما يبحث عنه |
|---|---|
-type f | الملفات العادية |
-type d | المجلدات |
-type l | الروابط الرمزية |
-type s | المقابس (sockets) |
-type p | الأنابيب المسماة (FIFO) |
# المجلدات التي اسمها logs فقط
find / -type d -name 'logs' 2>/dev/null
# الملفات الفارغة والمجلدات الفارغة
find . -type f -empty
find . -type d -empty
# الروابط الرمزية المعطوبة
find . -xtype l
البحث بالحجم: -size
يقبل الشرط -size رقماً مع لاحقة: c للبايت، وk للكيلوبايت، وM للميغابايت، وG للغيغابايت. والإشارة + تعني «أكبر من»، و- تعني «أصغر من»، وبدون إشارة تعني «يساوي تماماً».
# الملفات الأكبر من 100 ميغابايت في النظام كله
find / -type f -size +100M 2>/dev/null
# من 10 إلى 50 ميغابايت
find . -type f -size +10M -size -50M
# أصغر من كيلوبايت واحد
find . -type f -size -1k
هناك ملاحظة مهمة: يُقرَّب الحجم إلى الأعلى حسب وحدة القياس. لذلك يجد -size -1M الملفات الفارغة فقط، لأن أي ملف غير فارغ يُعدّ «ميغابايتاً واحداً على الأقل» بعد التقريب. وللحدود الدقيقة استخدم وحدات أصغر: -size -1024k.
ما الذي يشغل مساحة القرص
يعرض الجمع بين find وls وsort أكبر الملفات:
find /var -type f -size +50M -exec ls -lh {} + 2>/dev/null | sort -k5 -rh | head
-rw-r----- 1 syslog adm 1.2G Oct 14 09:12 /var/log/syslog.1
-rw-r--r-- 1 root root 412M Oct 10 03:00 /var/backups/db.sql.gz
-rw-r----- 1 root adm 96M Oct 14 09:15 /var/log/nginx/access.log
لتقدير حجم مجلدات كاملة يكون du -sh أنسب، أما find فمفيد حين يستهلك ملف واحد ضخم مساحةً كبيرة في عمق ما.
البحث بالتاريخ: -mtime وmmin وnewer
لكل ملف ثلاثة أختام زمنية، ويستطيع find التصفية بكل واحد منها:
| الشرط | الختم | الوحدة |
|---|---|---|
-mtime / -mmin | تغيير المحتوى | أيام / دقائق |
-atime / -amin | آخر قراءة | أيام / دقائق |
-ctime / -cmin | تغيير البيانات الوصفية (الصلاحيات، المالك، الاسم) | أيام / دقائق |
تعمل الإشارات كما في الحجم: -mtime -7 تعني عُدّل قبل أقل من 7 أيام، و-mtime +30 تعني قبل أكثر من 30 يوماً.
# المعدَّلة خلال الأسبوع الأخير
find ~/projects -type f -mtime -7
# السجلات الأقدم من 30 يوماً
find /var/log -type f -name '*.log' -mtime +30
# المعدَّلة خلال آخر 15 دقيقة
find /etc -type f -mmin -15
تُحسب الأيام فترات كاملة من 24 ساعة، والجزء الكسري يُهمل. لذلك يجد -mtime +1 الملفات الأقدم من 48 ساعة وليس 24 ساعة، وهذا فخ شائع. وإذا احتجت إلى دقة أكبر فانتقل إلى الدقائق: -mmin +1440.
الملفات الأحدث من ملف آخر أو من تاريخ
# المعدَّلة بعد آخر تعديل لملف deploy.lock
find . -type f -newer deploy.lock
# المعدَّلة بعد تاريخ محدد (GNU find)
find . -type f -newermt '2026-10-01'
# ضمن فترة تاريخية
find . -type f -newermt '2026-10-01' ! -newermt '2026-10-08'
البحث بالمالك والصلاحيات
# ملفات المستخدم alice
find /home -user alice
# ملفات بلا مالك موجود (بعد حذف مستخدم)
find / -nouser 2>/dev/null
# ملفات صلاحياتها 777 بالضبط
find /var/www -type f -perm 777
# ملفات قابلة للكتابة من الجميع
find /var/www -perm -o=w
# ملفات عليها بت SUID، مفيد في تدقيق الأمان
find / -perm -4000 -type f 2>/dev/null
للخيار -perm ثلاث صيغ: بدون إشارة تعني تطابق الصلاحيات تماماً، وبالإشارة - تعني أن كل البتات المذكورة مفعّلة على الأقل، وبالإشارة / تعني أن بتاً واحداً منها مفعّل على الأقل.
منطق الشروط: و، أو، نفي
تُربط الشروط افتراضياً بـ«و». ولـ«أو» يُستخدم -o، وللنفي ! أو -not. ويكون التجميع بالأقواس التي يجب أن تُهرَّب من الصدفة:
# صور jpg أو png
find . -type f \( -name '*.jpg' -o -name '*.png' \)
# كل شيء ما عدا ملفات .tmp
find . -type f ! -name '*.tmp'
بدون أقواس سيُطبَّق -type f على الشرط الأول من زوج «أو» فقط، فتدخل إلى النتيجة مجلدات باسم *.png. والمسافات حول \( و\) ضرورية.
عمق البحث: -maxdepth وmindepth
# في المجلد الحالي فقط، دون المجلدات المتداخلة
find . -maxdepth 1 -type f -name '*.sh'
# ابتداءً من المستوى الثاني من التداخل
find . -mindepth 2 -name '*.md'
# عدم الانتقال إلى أنظمة ملفات أخرى
find / -xdev -type f -size +1G
ضع -maxdepth مباشرةً بعد المسار وقبل بقية الشروط، وإلا فسيصدر GNU find تحذيراً. والخيار -xdev مفيد عند البحث من /: فلن يدخل find إلى /proc والأقراص الشبكية والأقراص المركّبة.
الإجراءات على النتائج: -exec و-delete وxargs
-exec: تنفيذ أمر لكل ملف
يضع find مكان {} مسار الملف. وينتهي الأمر بـ\; أو +:
# تشغيل واحد لكل ملف
find . -name '*.sh' -exec chmod +x {} \;
# كل الملفات في قائمة واحدة، وهو أسرع
find . -name '*.log' -exec gzip {} +
# مع تأكيد لكل ملف
find . -name '*.bak' -ok rm {} \;
الصيغة + تجمع المسارات في دفعات وتشغّل الأمر أقل بكثير، لذلك تكون أسرع بكثير عند آلاف الملفات. أما الصيغة \; فتُستخدم حين يقبل الأمر ملفاً واحداً فقط، أو حين لا يكون {} في نهاية الأمر.
-delete: حذف ما وُجد
# أولاً اعرض ما سيقع تحت الحذف
find /tmp/build -type f -name '*.o' -mtime +7
# ثم احذف
find /tmp/build -type f -name '*.o' -mtime +7 -delete
شغّل الأمر دائماً دون -delete وتحقق من القائمة. واجعل -delete في الآخر: إذ ينفّذ find التعبير من اليسار إلى اليمين، فإن find . -delete -name '*.o' سيحذف كل شيء في المجلد ثم يتحقق من الاسم.
find وxargs
الربط الكلاسيكي هو تمرير قائمة الملفات إلى برنامج آخر عبر xargs. ولكي لا يتعثر الأمر في الأسماء التي تحتوي على مسافات، استخدم فاصل البايت الصفري:
find . -type f -name '*.txt' -print0 | xargs -0 wc -l
يشغّل الخيار -P في xargs المعالجة بالتوازي:
find ./images -name '*.png' -print0 | xargs -0 -P 4 -n 10 optipng
find وgrep: البحث عن نص داخل الملفات
يبحث find عن الملفات لا عن محتواها. ولإيجاد سطر داخل الملفات المختارة، مرّرها إلى grep:
# أين يرد listen 8080 في ملفات الإعداد
find /etc/nginx -type f -name '*.conf' -exec grep -Hn 'listen 8080' {} +
/etc/nginx/sites-enabled/app.conf:4: listen 8080;
الخيار -H يطبع اسم الملف، و-n يطبع رقم السطر، وgrep -l يطبع أسماء الملفات التي وجد فيها التطابق فقط. وإذا كان التصفية بالامتداد فقط، يكفي grep نفسه: grep -rn --include='*.conf' 'listen 8080' /etc/nginx.
تنسيق مخصص للمخرجات: -printf
يستطيع GNU find طباعة أكثر من المسار. مثلاً الحجم والتاريخ والاسم:
find . -maxdepth 1 -type f -printf '%s\t%TY-%Tm-%Td\t%p\n' | sort -n
هنا %s الحجم بالبايت، و%T... تاريخ التعديل مقسّماً إلى أجزاء، و%p المسار. وهذا مفيد في السكريبتات، لأنه لا يحتاج إلى تحليل مخرجات ls.
ورقة مرجعية: أمثلة find في Linux لكل يوم
| المهمة | الأمر |
|---|---|
| البحث عن ملف بالاسم | find / -name 'file.txt' 2>/dev/null |
| دون مراعاة حالة الأحرف | find . -iname '*.jpg' |
| المجلدات فقط | find . -type d -name 'cache' |
| الملفات الأكبر من 1 غيغابايت | find / -xdev -type f -size +1G |
| المعدَّلة خلال يوم | find . -type f -mtime -1 |
| المعدَّلة خلال ساعة | find . -type f -mmin -60 |
| حذف السجلات الأقدم من 30 يوماً | find /var/log/app -name '*.log' -mtime +30 -delete |
| المجلدات الفارغة | find . -type d -empty |
| تغيير صلاحيات كل المجلدات | find . -type d -exec chmod 755 {} + |
| نص داخل الملفات | find . -name '*.py' -exec grep -l 'TODO' {} + |
| عدّ الملفات | find . -type f | wc -l |
الأخطاء الشائعة
- النمط دون علامات اقتباس. الأمر
find . -name *.logيفشل إذا وُجد ملف.logواحد في المجلد الحالي. اكتب'*.log'. - سيل من Permission denied. أضف
2>/dev/null، أو شغّل الأمر عبرsudoإذا كنت تحتاج فعلاً إلى القرص كله. -deleteفي غير مكانه. يجب أن يكون في الآخر، وقبله تشغيل تجريبي بلا حذف.- أسماء بمسافات في خط الأنابيب. الأمر
find ... | xargs rmيقطع الملف «My File.txt» إلى معاملين. استخدم-print0معxargs -0، أو-exec. - توقع أياماً دقيقة من
-mtime. للفترات الدقيقة استخدم-mminأو-newermt.
الخلاصة
find أداة شاملة للبحث في نظام الملفات: المسار، ثم الشروط بالاسم والنوع والحجم والتاريخ والصلاحيات، ثم الإجراء. أتقن خمسة عناصر — -name و-type و-size و-mtime و-exec ... + — فتُحل معظم المهام بسطر واحد. ينبغي تجربة أمثلة find في Linux الواردة هنا في طرفيتك، وقد جرى شرح الجمع بين find وgrep وsed وawk عملياً في درس Linux عن معالجة النصوص في الطرفية.
الأسئلة الشائعة
ما الفرق بين find وlocate؟
يبحث locate في قاعدة أسماء بُنيت مسبقاً، لذلك يعمل فورياً لكنه لا يرى الملفات التي أُنشئت بعد آخر تحديث لها بالأمر updatedb. أما find فيمر على القرص آنياً، ويستطيع التصفية بالحجم والتاريخ والصلاحيات.
كيف أجد ملفاً بمحتواه لا باسمه؟
find نفسه لا يقرأ المحتوى. استخدم grep -rn 'النص' /المسار، أو الجمع find . -name '*.conf' -exec grep -l 'النص' {} +.
لماذا يعمل find ببطء على جذر القرص؟
لأنه يمر على كل المجلدات، بما فيها /proc و/sys والأقراص المركّبة. قيّد البحث بمجلد محدد، وأضف -xdev وmaxdepth، أو استبعد الزائد عبر -prune.
هل يمكن ترتيب نتائج find حسب التاريخ؟
نعم: find . -type f -printf '%T@ %p\n' | sort -n يعرض الملفات من الأقدم إلى الأحدث، حيث %T@ هو وقت التعديل بالثواني منذ بداية الحقبة.
كيف أجد المجلدات الفارغة وأحذفها؟
الأمر find . -type d -empty -delete يحذف كل المجلدات الفارغة، بما فيها التي أصبحت فارغة بعد حذف ما بداخلها. شغّله أولاً دون -delete وتحقق من القائمة.
يُشرح هذا الموضوع بالتفصيل مع التطبيق العملي في دورة «Linux: с нуля до уверенного администрирования».
الانتقال إلى الدورة