คำสั่ง find ของ Linux: ตัวเลือก -name, -type, -size, -mtime และ -delete
คำสั่ง find ของ Linux ไล่ลงไปจากโฟลเดอร์เริ่มต้นและค้นหาไฟล์กับโฟลเดอร์ที่ตรงตามเงื่อนไข เช่น ชื่อ ประเภท ขนาด เวลาแก้ไข และสิทธิ์ เมื่อเราสร้างไฟล์สิบไฟล์ในโฟลเดอร์ทดสอบบนเซิร์ฟเวอร์ AlmaLinux 9 แล้วรันโดยเปลี่ยนเงื่อนไขทีละอย่าง จึงได้ส่งไฟล์ที่พบด้วย -exec ไปยังคำสั่งอื่น และเมื่อจะลบก็ตรวจรายการด้วยเงื่อนไขเดียวกันก่อนใช้ -delete
พาธโฟลเดอร์ทดสอบและเวลาของไฟล์ในกล่องผลลัพธ์ถูกเปลี่ยนเป็นค่าตัวอย่าง ส่วนเอาต์พุตจากเซิร์ฟเวอร์ Debian 12 มีเพียงพาธโฟลเดอร์โฮมที่เป็นค่าตัวอย่าง ที่เหลือคงเดิม
1️⃣ วิธีใช้คำสั่ง find ของ Linux
รูปแบบพื้นฐานคือ [find พาธเริ่มต้น เงื่อนไข] ถ้าไม่เขียนพาธเริ่มต้นจะค้นในโฟลเดอร์ปัจจุบัน (.) และถ้าไม่เขียนเงื่อนไขจะแสดงไฟล์และโฟลเดอร์ทั้งหมดใต้พาธเริ่มต้น
การทดสอบทำใน /root/work ที่มีสามโฟลเดอร์และสิบไฟล์ดังด้านล่าง
find /root/work/root/work
/root/work/docs
/root/work/docs/readme.txt
/root/work/docs/guide.txt
/root/work/docs/old.tmp
/root/work/logs
/root/work/logs/app.log
/root/work/logs/cache.tmp
/root/work/backup
/root/work/report.txt
/root/work/README.md
/root/work/run.sh
/root/work/my notes.txt
/root/work/empty.txtfind ไม่เรียงผลลัพธ์ตามชื่อ ในการรันครั้งนี้ เมื่อถึงโฟลเดอร์ docs ก็แสดงไฟล์ข้างในทั้งหมดก่อนแล้วจึงไปต่อที่ logs
ถ้าเขียนหลายเงื่อนไขต่อกัน จะเหลือเฉพาะไฟล์ที่ตรงทุกเงื่อนไข
-name เปรียบเทียบแพตเทิร์นกับชื่อไฟล์เท่านั้น ไม่ใช่พาธ ควรครอบแพตเทิร์นด้วยเครื่องหมายคำพูดเดี่ยวเพื่อให้เชลล์ไม่ขยาย * ก่อนและส่งให้ find ตามเดิม
find /root/work -name '*.txt'/root/work/docs/readme.txt
/root/work/docs/guide.txt
/root/work/report.txt
/root/work/my notes.txt
/root/work/empty.txt-name แยกตัวพิมพ์ใหญ่เล็ก เมื่อค้นหาชื่อที่ขึ้นต้นด้วย readme พบเพียง docs/readme.txt และเมื่อเปลี่ยนเป็น -iname ก็พบ README.md ด้วย
find /root/work -name 'readme*'/root/work/docs/readme.txtfind /root/work -iname 'readme*'/root/work/docs/readme.txt
/root/work/README.mdfind อยู่ในแพ็กเกจ findutils เวอร์ชันจากบรรทัดแรกของ [find --version] คือ findutils 4.8 บนเซิร์ฟเวอร์ AlmaLinux 9.8 และ 4.9 บนเซิร์ฟเวอร์ Debian 12
2️⃣ find -type d และ -maxdepth
-type f เหลือเฉพาะไฟล์ปกติ และ -type d เหลือเฉพาะโฟลเดอร์
find /root/work -type d/root/work
/root/work/docs
/root/work/logs
/root/work/backupพาธเริ่มต้น /root/work ก็เป็นโฟลเดอร์ จึงแสดงในบรรทัดแรกด้วย เมื่อเปลี่ยนเป็น -type f ในพาธเดิมก็แสดงไฟล์ครบสิบไฟล์
-maxdepth กำหนดว่าจะลงจากพาธเริ่มต้นไปกี่ชั้น เมื่อรันด้วย -maxdepth 1 ไฟล์ใน docs และ logs หายไป เหลือเพียงห้าไฟล์ใต้ /root/work โดยตรง
find /root/work -maxdepth 1 -type f/root/work/report.txt
/root/work/README.md
/root/work/run.sh
/root/work/my notes.txt
/root/work/empty.txtในทางกลับกัน -mindepth 2 ข้ามสิ่งที่อยู่ใต้พาธเริ่มต้นโดยตรง และแสดงเฉพาะห้าไฟล์ในโฟลเดอร์ย่อย
find /root/work -mindepth 2 -type f/root/work/docs/readme.txt
/root/work/docs/guide.txt
/root/work/docs/old.tmp
/root/work/logs/app.log
/root/work/logs/cache.tmpหน้า man แนะนำให้เขียนตัวเลือกส่วนกลางอย่าง -maxdepth ไว้หลังพาธเริ่มต้นทันที แม้เขียน -maxdepth 1 หลัง -type f ผลก็ยังเป็นห้าไฟล์เดิม แต่ในเทอร์มินัลจะมีคำเตือนหนึ่งบรรทัดให้เขียนตัวเลือกส่วนกลางไว้ก่อน (อ้างอิงหน้า man)
ถ้าต้องการรู้เฉพาะจำนวนโฟลเดอร์หรือไฟล์ ให้ส่งเอาต์พุตไปยัง wc -l เมื่อนับเอาต์พุต -type d ได้ 4 รวมพาธเริ่มต้น
find /root/work -type d | wc -l4เมื่อใส่ -maxdepth 1 ก็ได้ 4 เช่นกัน เพราะโฟลเดอร์ย่อยทั้งสามอยู่ใต้พาธเริ่มต้นโดยตรง
find /root/work -maxdepth 1 -type d | wc -l4เมื่อนับเฉพาะไฟล์ในโฟลเดอร์ย่อยด้วย -mindepth 2 ได้ 5
find /root/work -mindepth 2 -type f | wc -l53️⃣ เงื่อนไขขนาดและเวลาของคำสั่ง find
+ หน้าตัวเลขหมายถึงมากกว่าค่านั้น - หมายถึงน้อยกว่า และถ้าไม่มีเครื่องหมายหมายถึงเท่ากับค่านั้นพอดี หน่วยของ -size อยู่ในตารางด้านล่าง (อ้างอิงหน้า man)
| หน่วย | ขนาด | ใช่ |
|---|---|---|
| c | 1 ไบต์ | -size +500c |
| k | 1,024 ไบต์ | -size +1k |
| M | 1,048,576 ไบต์ | -size +1M |
| G | 1,073,741,824 ไบต์ | -size +1G |
| (ไม่มี) | บล็อก 512 ไบต์ | -size +2 |
find /root/work -type f -size +1k/root/work/docs/guide.txt
/root/work/logs/app.log
/root/work/report.txtไฟล์ที่ใหญ่กว่า 1k คือ guide.txt 5,000 ไบต์, app.log 2MB และ report.txt 1,200 ไบต์
find /root/work -size +1M/root/work/logs/app.logเมื่อเขียน -size สองครั้งเพื่อกำหนดช่วง เหลือเพียงสองไฟล์ที่ใหญ่กว่า 1k และเล็กกว่า 100k
find /root/work -type f -size +1k -size -100k/root/work/docs/guide.txt
/root/work/report.txt-size หารขนาดด้วยหน่วยแล้วปัดขึ้นก่อนเปรียบเทียบ ดังนั้น README.md ขนาด 300 ไบต์จึงนับเป็น 1k และ -size -1k แสดงเพียง empty.txt ที่มีขนาด 0
find /root/work -type f -size -1k/root/work/empty.txtเพื่อดูเงื่อนไขเวลา เราตั้งเวลาแก้ไขของ README.md, my notes.txt และ docs/readme.txt เป็น 3 วันก่อน และไฟล์ .tmp สองไฟล์เป็น 10 วันก่อน แต่ละไฟล์มีเวลาสามแบบคือ เข้าถึง แก้ไข และเปลี่ยนแปลง ซึ่งตรวจดูได้ด้วย คำสั่ง stat ได้เช่นกัน
-mtime นับเวลาตั้งแต่แก้ไขล่าสุดเป็นหน่วย 24 ชั่วโมง -mtime -1 แสดงห้าไฟล์ที่สร้างภายใน 24 ชั่วโมง
find /root/work -type f -mtime -1/root/work/docs/guide.txt
/root/work/logs/app.log
/root/work/report.txt
/root/work/run.sh
/root/work/empty.txt-mtime +7 แสดงเฉพาะไฟล์ .tmp สองไฟล์ที่ตั้งเป็น 10 วันก่อน ใช้รูปแบบนี้เพื่อตรวจรายการก่อนลบล็อกเก่าหรือไฟล์ชั่วคราว
find /root/work -type f -mtime +7/root/work/docs/old.tmp
/root/work/logs/cache.tmp-mmin คำนวณแบบเดียวกันเป็นนาที ผลของ -mmin -60 คือห้าไฟล์เดียวกับ -mtime -1
find /root/work -type f -mmin -60/root/work/docs/guide.txt
/root/work/logs/app.log
/root/work/report.txt
/root/work/run.sh
/root/work/empty.txt-newer ค้นหาไฟล์ที่แก้ไขหลังไฟล์อ้างอิง เมื่อใช้ README.md ที่ตั้งเป็น 3 วันก่อนเป็นเกณฑ์ ได้ห้าไฟล์ที่สร้างหลังจากนั้น
find /root/work -type f -newer /root/work/README.md/root/work/docs/guide.txt
/root/work/logs/app.log
/root/work/report.txt
/root/work/run.sh
/root/work/empty.txt-empty ค้นหาทั้งไฟล์ขนาด 0 และโฟลเดอร์ว่าง จึงพบโฟลเดอร์ว่าง backup และ empty.txt
find /root/work -empty/root/work/backup
/root/work/empty.txt4️⃣ เงื่อนไข -perm และ -user ของ find
ถ้าเขียนเฉพาะตัวเลขหลัง -perm จะค้นหาไฟล์ที่มีสิทธิ์ตรงค่านั้นพอดี -perm 644 ไม่รวม run.sh ที่เป็น 755 และ my notes.txt ที่เป็น 600 และพบแปดไฟล์
find /root/work -type f -perm 644/root/work/docs/readme.txt
/root/work/docs/guide.txt
/root/work/docs/old.tmp
/root/work/logs/app.log
/root/work/logs/cache.tmp
/root/work/report.txt
/root/work/README.md
/root/work/empty.txtถ้าใส่ - หน้าโหมดจะค้นหาไฟล์ที่มีสิทธิ์ที่เขียนไว้ครบทั้งหมด ไฟล์ที่มีสิทธิ์รันของเจ้าของ (u+x) มีเพียง run.sh
find /root/work -type f -perm -u+x/root/work/run.shถ้าใส่ / หน้าโหมด เพียงมีสิทธิ์ใดสิทธิ์หนึ่งก็พบ 6000 คือผลรวมของ SUID (4000) และ SGID (2000) ใช้รูปแบบนี้ตรวจไฟล์บนเซิร์ฟเวอร์ที่เมื่อรันแล้วทำงานด้วยสิทธิ์ของเจ้าของหรือกลุ่ม
ในโฟลเดอร์ทดสอบไม่มีไฟล์แบบนี้ จึงให้ SUID กับ run.sh แล้วรัน ได้ run.sh หนึ่งไฟล์
chmod u+s /root/work/run.shfind /root/work -type f -perm /6000/root/work/run.shเอกสารเก่าเขียน -perm +6000 ไว้ตรงตำแหน่งเดียวกัน เมื่อรันตามนั้นจบด้วยข้อผิดพลาด [invalid mode]
find /root/work -type f -perm +6000find: invalid mode '+6000'รูปแบบ + ถูกนำออกใน findutils 4.5.12 (อ้างอิงหน้า man) จึงต้องเขียน / SUID ที่ให้ไว้เพื่อทดสอบถูกลบด้วย chmod u-s
-user กรองตามชื่อเจ้าของ ไฟล์ทดสอบทั้งหมดเป็นของ root ดังนั้น -user root อย่างเดียวจึงกรองอะไรไม่ได้ เมื่อเพิ่ม -name เพื่อเลือกไฟล์ .log จึงได้ app.log หนึ่งไฟล์
find /root/work -type f -user root -name '*.log'/root/work/logs/app.log-nouser ค้นหาไฟล์ที่ UID เจ้าของไม่ตรงกับบัญชีใด ใช้ตรวจไฟล์ที่ค้างอยู่บนเซิร์ฟเวอร์หลังลบบัญชี เมื่อเปลี่ยนเจ้าของ guide.txt เป็น UID 1500 ที่ไม่มีอยู่ ได้ guide.txt หนึ่งไฟล์
chown 1500:1500 /root/work/docs/guide.txtfind /root/work -nouser/root/work/docs/guide.txt-nogroup ตรวจแบบเดียวกันกับกลุ่มเจ้าของ และพบ guide.txt ที่เปลี่ยนกลุ่มเป็น 1500 ด้วย หลังทดสอบเสร็จเราคืนค่าด้วย chown root:root
ถ้าใส่ -o ระหว่างเงื่อนไข เพียงตรงเงื่อนไขเดียวก็พอ เมื่อใช้ร่วมกับเงื่อนไขอื่นอย่าง -type f ให้ครอบเงื่อนไขที่เชื่อมด้วย -o ด้วยวงเล็บ ใส่แบ็กสแลชหน้าวงเล็บเพื่อไม่ให้เชลล์ตีความก่อน และเว้นวรรคระหว่างวงเล็บกับเงื่อนไข
find /root/work -type f \( -name '*.log' -o -name '*.tmp' \)/root/work/docs/old.tmp
/root/work/logs/app.log
/root/work/logs/cache.tmp! กลับเงื่อนไขที่อยู่ถัดไป เมื่อค้นหาไฟล์ที่ไม่ใช่ .txt พบห้าไฟล์
find /root/work -type f ! -name '*.txt'/root/work/docs/old.tmp
/root/work/logs/app.log
/root/work/logs/cache.tmp
/root/work/README.md
/root/work/run.sh5️⃣ การใช้ find -exec
-exec รันคำสั่งที่เขียนไว้ข้างหลังกับไฟล์ที่พบแต่ละไฟล์ โดยใส่พาธที่พบแทน {} เครื่องหมาย ; ท้ายคำสั่งต้องเขียนเป็น \; เพื่อไม่ให้เชลล์อ่านเป็นตัวคั่นคำสั่งก่อน
find /root/work -name '*.log' -exec ls -l {} \;-rw-r--r-- 1 root root 2097152 Oct 5 14:10 /root/work/logs/app.logถ้าจบด้วย + แทน \; พาธที่พบจะถูกรวมแล้วรันคำสั่งครั้งเดียว เมื่อเทียบด้วย echo \; แสดงห้าพาธเป็นห้าบรรทัด ส่วน + แสดงเป็นบรรทัดเดียว
find /root/work -name '*.txt' -exec echo {} \;/root/work/docs/readme.txt
/root/work/docs/guide.txt
/root/work/report.txt
/root/work/my notes.txt
/root/work/empty.txtfind /root/work -name '*.txt' -exec echo {} +/root/work/docs/readme.txt /root/work/docs/guide.txt /root/work/report.txt /root/work/my notes.txt /root/work/empty.txtคำสั่งที่รับหลายพาธอย่าง ls ให้รวมด้วย + เพื่อลดจำนวนครั้งที่รัน เราตรวจขนาดของสามไฟล์ที่ใหญ่กว่า 1k ด้วย ls -lh ครั้งเดียว
find /root/work -type f -size +1k -exec ls -lh {} +-rw-r--r-- 1 root root 4.9K Oct 5 14:10 /root/work/docs/guide.txt
-rw-r--r-- 1 root root 2.0M Oct 5 14:10 /root/work/logs/app.log
-rw-r--r-- 1 root root 1.2K Oct 5 14:10 /root/work/report.txt-exec ยังใช้จัดสิทธิ์ของโฟลเดอร์เว็บทีละมากๆ เป็น 644 สำหรับไฟล์และ 755 สำหรับโฟลเดอร์ ก่อนรันเราค้นหาไฟล์ที่ค่าต่างออกไป และพบ run.sh กับ my notes.txt
find /root/work -type f ! -perm 644/root/work/run.sh
/root/work/my notes.txtไฟล์และโฟลเดอร์มีสิทธิ์ต่างกัน จึงรันแยกด้วย -type f และ -type d chmod ก็รับหลายพาธ จึงจบด้วย +
find /root/work -type f -exec chmod 644 {} +find /root/work -type d -exec chmod 755 {} +เมื่อค้นหาอีกครั้งด้วยเงื่อนไขเดิมก็ไม่พบอะไร และโฟลเดอร์ backup ที่เปลี่ยนเป็น 700 ไว้ก่อนก็กลายเป็น 755
แต่ run.sh ก็กลายเป็น 644 ด้วย เมื่อรันจึงได้ [Permission denied] ในโฟลเดอร์ที่มีไฟล์รันได้ปนอยู่ ให้คืนสิทธิ์รันแก่ไฟล์เหล่านั้นด้วย chmod +x
ถ้าต้องการเปลี่ยนเฉพาะไฟล์ในโฟลเดอร์ย่อย ให้ใส่ -mindepth 2 เมื่อรันด้วย 660 มีเพียงห้าไฟล์ใน docs และ logs ที่เปลี่ยน และเราคืนเป็น 644 หลังตรวจแล้ว
find /root/work -mindepth 2 -type f -exec chmod 660 {} +find /root/work -type f -perm 660/root/work/docs/readme.txt
/root/work/docs/guide.txt
/root/work/docs/old.tmp
/root/work/logs/app.log
/root/work/logs/cache.tmpเมื่อเชื่อม find กับ grep จะค้นหาตามเนื้อหาไฟล์แทนชื่อได้ เพื่อจำลองการตรวจเว็บเชลล์ เราสร้างไฟล์ PHP สี่ไฟล์ในโฟลเดอร์แยก /root/site และใส่สตริง [base64_decode] ใน html-cache.php และ photo.php ของโฟลเดอร์ upload
find /root/site -type f/root/site/lib/func.php
/root/site/upload/html-cache.php
/root/site/upload/photo.php
/root/site/index.phpถ้ารู้ชื่อเว็บเชลล์ให้ค้นด้วย -name เมื่อใส่ -maxdepth 2 เพื่อลงไปแค่โฟลเดอร์อัปโหลด พบเพียง html-cache.php
find /root/site -maxdepth 2 -type f -name 'html*.php'/root/site/upload/html-cache.phpphoto.php ที่เปลี่ยนชื่อให้ธรรมดาไม่ปรากฏตรงนี้ เมื่อรัน grep -l ผ่าน -exec จะแสดงเฉพาะพาธของไฟล์ที่มีสตริง และพบทั้งสองไฟล์
find /root/site -name '*.php' -exec grep -l 'base64_decode' {} +/root/site/upload/html-cache.php
/root/site/upload/photo.php[base64_decode] เป็นฟังก์ชันที่มีอยู่ในไฟล์แกนหลักของ WordPress ด้วย จึงต้องเปิดดูเนื้อหาไฟล์ที่พบก่อนลบ
-print0 ใส่อักขระ null แทนการขึ้นบรรทัดใหม่ระหว่างพาธ อักขระ null มองไม่เห็นบนหน้าจอ พาธจึงแสดงติดกันในบรรทัดเดียว
find /root/work -name '*.txt' -print0/root/work/docs/readme.txt/root/work/docs/guide.txt/root/work/report.txt/root/work/my notes.txt/root/work/empty.txtเมื่อส่งชื่อที่มีช่องว่างอย่าง my notes.txt ไปยังคำสั่งอื่นโดยไม่ให้ขาดกัน ให้ใช้เอาต์พุต -print0 คู่กับ xargs -0 (อ้างอิงหน้า man)
6️⃣ การลบไฟล์ด้วย find และตัวเลือก
ก่อนลบให้รันเงื่อนไขเดียวกันโดยไม่ลบก่อน แล้วตรวจรายการไฟล์ที่จะลบด้วยตาตนเอง
find /root/work -name '*.tmp'/root/work/docs/old.tmp
/root/work/logs/cache.tmp-exec rm {} \; รัน rm กับไฟล์ที่พบแต่ละไฟล์ เมื่อรันเฉพาะในโฟลเดอร์ logs cache.tmp ถูกลบและเหลือเพียง app.log
find /root/work/logs -name '*.tmp' -exec rm {} \;ls /root/work/logsapp.log-delete ให้ find ลบเองโดยไม่ต้องรัน rm เมื่อรันแล้วไม่แสดงอะไร และเมื่อค้นหาอีกครั้งด้วยเงื่อนไขเดิมก็ไม่มีไฟล์ .tmp เหลือ
find /root/work -name '*.tmp' -deletefind /root/work -name '*.tmp'-delete ต้องเขียนหลังเงื่อนไขเสมอ find คำนวณบรรทัดคำสั่งจากด้านหน้าเป็นนิพจน์เดียว ถ้าวาง -delete ไว้หน้าสุด จะพยายามลบทุกอย่างใต้พาธเริ่มต้นก่อนดูเงื่อนไข (อ้างอิงหน้า man)
🔲 ตัวเลือกของคำสั่ง find
📌 ตัวเลือกหลัก: ผลที่รันในบทความนี้
| ตัวเลือก | หน้าที่ | ผลที่เห็นในบทความนี้ | |
|---|---|---|---|
| -name | ค้นหาชื่อที่ตรงกับแพตเทิร์น (แยกตัวพิมพ์ใหญ่เล็ก) | '*.txt' ได้ห้าไฟล์ 'readme*' ได้เฉพาะ docs/readme.txt | |
| -iname | เปรียบเทียบชื่อโดยไม่แยกตัวพิมพ์ใหญ่เล็ก | 'readme*' ได้ docs/readme.txt และ README.md | |
| -type f, -type d | เหลือเฉพาะไฟล์ปกติ (f) หรือโฟลเดอร์ (d) | -type d ได้สี่โฟลเดอร์รวมพาธเริ่มต้น -type f ได้สิบไฟล์ | |
| -maxdepth | ลงไปไม่เกิน N ชั้นจากพาธเริ่มต้น | -maxdepth 1 เหลือเพียงห้าไฟล์ใต้ /root/work โดยตรง | |
| -mindepth | ข้ามชั้นที่อยู่เหนือ N ชั้นจากพาธเริ่มต้น | -mindepth 2 ได้เฉพาะห้าไฟล์ในโฟลเดอร์ย่อย | |
| -size | ค้นหาตามขนาด (+ ใหญ่กว่า - เล็กกว่า หน่วย c, k, M, G) | -size +1k ได้สามไฟล์ -size -1k ได้เฉพาะ empty.txt | |
| -mtime | เปรียบเทียบเวลาหลังแก้ไขเนื้อหาเป็นหน่วย 24 ชั่วโมง | -mtime -1 ได้ห้าไฟล์ -mtime +7 ได้ไฟล์ .tmp สองไฟล์ | |
| -mmin | เปรียบเทียบเวลาหลังแก้ไขเป็นนาที | -mmin -60 ได้ห้าไฟล์เดียวกับ -mtime -1 | |
| -ctime | เปรียบเทียบเป็นหน่วย 24 ชั่วโมงถึงเวลาที่ข้อมูลไฟล์อย่างสิทธิ์และชื่อเปลี่ยน | -ctime -1 ได้ไฟล์ทดสอบครบสิบไฟล์ | |
| -newer | ค้นหาสิ่งที่แก้ไขหลังไฟล์อ้างอิง | ใช้ README.md ที่ตั้งเป็น 3 วันก่อนเป็นเกณฑ์ ได้ห้าไฟล์ | |
| -empty | ค้นหาไฟล์ขนาด 0 และโฟลเดอร์ว่าง | ได้โฟลเดอร์ว่าง backup และ empty.txt | |
| -perm | ค้นหาตามสิทธิ์ (ตัวเลขอย่างเดียว: ตรงค่านั้น ใส่ - หน้า: มีครบทุกสิทธิ์ ใส่ / หน้า: มีอย่างน้อยหนึ่งสิทธิ์) | -perm 644 ได้แปดไฟล์ -perm -u+x ได้ run.sh หลังให้ SUID แล้ว -perm /6000 ได้ run.sh | |
| -user | กรองตามชื่อเจ้าของ | ใช้ร่วมกับ -name '*.log' ได้ app.log บัญชีที่ไม่มีอยู่จบด้วยข้อผิดพลาด | |
| -nouser | ค้นหาสิ่งที่ UID เจ้าของไม่มีบัญชี | ได้ guide.txt ที่เปลี่ยน UID เป็น 1500 | |
| -nogroup | ค้นหาสิ่งที่ GID กลุ่มไม่มีกลุ่ม | ได้ guide.txt ที่เปลี่ยน GID เป็น 1500 | |
| -o | เหลือสิ่งที่ตรงอย่างใดอย่างหนึ่ง (ครอบวงเล็บเมื่อใช้กับเงื่อนไขอื่น) | รวม .log และ .tmp ได้สามไฟล์ | |
| ! | กลับเงื่อนไขที่อยู่ถัดไป | ได้ห้าไฟล์ที่ไม่ใช่ .txt | |
| -exec | รันคำสั่งที่เขียนไว้หลังกับไฟล์ที่พบแต่ละไฟล์ (พาธอยู่ที่ {}) | จบด้วย + แล้ว echo ครั้งเดียวแสดงห้าพาธในบรรทัดเดียว | |
| -print0 | ใส่อักขระ null แทนการขึ้นบรรทัดใหม่ระหว่างพาธ | อักขระ null มองไม่เห็น พาธจึงติดกันในบรรทัดเดียว | |
| -delete | find ลบไฟล์ที่พบเอง (เขียนหลังเงื่อนไข) | ไม่แสดงอะไร เมื่อค้นอีกครั้งไม่มีไฟล์ .tmp |
📎 ตัวเลือกอื่น: ตามคู่มือทางการ
| ตัวเลือก | หน้าที่ | |
|---|---|---|
| -L | ตามลิงก์สัญลักษณ์และใช้ข้อมูลของไฟล์ปลายทาง | |
| -path | เปรียบเทียบทั้งพาธแทนชื่อกับแพตเทิร์นของเชลล์ | |
| -regex | เปรียบเทียบทั้งพาธกับนิพจน์ปกติ | |
| -iregex | เปรียบเทียบแบบ -regex โดยไม่แยกตัวพิมพ์ใหญ่เล็ก | |
| -atime | เปรียบเทียบเวลาหลังเข้าถึงล่าสุดเป็นหน่วย 24 ชั่วโมง | |
| -cnewer | ค้นหาสิ่งที่สถานะเปลี่ยนหลังเวลาแก้ไขของไฟล์อ้างอิง | |
| -group | กรองตามชื่อกลุ่มเจ้าของ | |
| -xdev | ไม่ลงไปในโฟลเดอร์ของระบบไฟล์อื่น | |
| -daystart | คำนวณเงื่อนไขเวลาจาก 0 นาฬิกาของวันนี้แทน 24 ชั่วโมงก่อน | |
| -prune | ถ้าเป็นโฟลเดอร์จะไม่ลงไปข้างใน | |
| -quit | จบทันที (-print -quit แสดงเฉพาะผลแรก) | |
| -printf | แสดงผลตามรูปแบบที่กำหนดเอง | |
| -ls | แสดงไฟล์ที่พบในรูปแบบ ls -dils | |
| -fprint | บันทึกพาธที่พบลงไฟล์ที่ระบุแทนหน้าจอ | |
| -ok | ทำงานแบบ -exec แต่ถามก่อน | |
| -execdir | ทำงานแบบ -exec แต่รันคำสั่งในโฟลเดอร์ของไฟล์ที่พบ |
🔲 ตัวจำลองคำสั่ง find
ตัวจำลองด้านล่างคือเซิร์ฟเวอร์เสมือนที่มีโฟลเดอร์ทดสอบเดียวกัน คุณรันเงื่อนไขอย่าง -name, -type, -size, -mtime, -perm รวมถึง -exec และ -delete ได้เอง
7️⃣ ข้อผิดพลาดของคำสั่ง find
ถ้าเขียนแพตเทิร์นโดยไม่ครอบเครื่องหมายคำพูด เชลล์จะใช้กฎของ ไวลด์การ์ด ขยายเป็นชื่อไฟล์ในโฟลเดอร์ปัจจุบันก่อน เมื่อไปที่โฟลเดอร์ docs แล้วเขียน *.txt โดยไม่ครอบเครื่องหมายคำพูด เชลล์เปลี่ยนเป็นสองชื่อคือ guide.txt และ readme.txt แล้วส่งไป จึงเกิดข้อผิดพลาดด้านล่าง
cd /root/work/docsfind /root/work -name *.txtfind: paths must precede expression: `readme.txt'
find: possible unquoted pattern after predicate `-name'?รหัสออกคือ 1
เมื่อไม่ใส่ \; หรือ + ท้าย -exec จะได้ [missing argument to `-exec’]
find /root/work -name '*.log' -exec ls -l {}find: missing argument to `-exec'พาธเริ่มต้นที่ไม่มีอยู่ให้ [No such file or directory] และจบด้วยรหัสออก 1
find /nonexistent-dir -name xfind: '/nonexistent-dir': No such file or directoryชื่อบัญชีที่ไม่มีอยู่ใน -user หรือค่าใน -type ที่ไม่ใช่ตัวอักษรที่กำหนดอย่าง f และ d จะจบด้วยข้อผิดพลาดทันทีโดยไม่เริ่มค้นหา
find /root/work -user nosuchuserfind: 'nosuchuser' is not the name of a known userfind /root/work -type xfind: Unknown argument to -type: xด้วยบัญชีปกติบนเซิร์ฟเวอร์ Debian 12 เราเปลี่ยนสิทธิ์ของโฟลเดอร์ lock ในโฟลเดอร์ทดสอบเป็น 000 แล้วค้นในโฟลเดอร์ทดสอบ อ่านข้างใน lock ไม่ได้ จึงได้ [Permission denied] และรหัสออกคือ 1
find ~/findtest/home/user/findtest
/home/user/findtest/report.txt
/home/user/findtest/lock
find: '/home/user/findtest/lock': Permission denied
/home/user/findtest/docs
/home/user/findtest/docs/readme.txtถ้าต้องการซ่อนเฉพาะบรรทัดข้อผิดพลาด ให้ใส่ 2>/dev/null ข้อความผิดพลาดหายไป แต่รหัสออกยังเป็น 1
find ~/findtest -name '*.txt' 2>/dev/null/home/user/findtest/report.txt
/home/user/findtest/docs/readme.txt🔢 FAQ & เนื้อหาแนะนำ
การค้นหาเนื้อหา
คำสั่ง grep ของ Linux
บทความเกี่ยวกับคำสั่ง grep ที่หาข้อความในไฟล์และแสดงบรรทัดนั้น พร้อมตัวเลือก
การลบ
คำสั่ง rm ของ Linux: ตัวเลือก rm -rf และวิธีลบโดยไม่ต้องยืนยัน
บทความเกี่ยวกับตัวเลือก -r, -f และคำถามยืนยันของคำสั่ง rm เมื่อลบไฟล์และโฟลเดอร์
พื้นที่ดิสก์
คำสั่ง du: การตรวจพื้นที่ดิสก์ของไฟล์
บทความเกี่ยวกับการรวมพื้นที่ดิสก์ที่โฟลเดอร์และไฟล์ใช้ด้วยคำสั่ง du
ℹ️ ประกาศเรื่องลิงก์แอฟฟิลิเอต
เนื้อหาของเว็บไซต์นี้มีลิงก์แอฟฟิลิเอต หากผู้เข้าชมซื้อสินค้าหรือบริการผ่านลิงก์เหล่านี้ เว็บไซต์นี้จะได้รับค่าคอมมิชชันจากผู้ขาย ในกระบวนการนี้ ราคาที่ผู้ซื้อจ่าย(ราคาจะลดลงเมื่อมีโปรโมชัน↓)จะไม่สูงขึ้นแต่อย่างใด ราคา ส่วนลด และข้อมูลสต็อกที่แสดงเป็นข้อมูล ณ เวลาที่เขียนและอาจต่างจากความเป็นจริง โปรดตรวจสอบกับผู้ขายอีกครั้งก่อนซื้อ การเลือกและการประเมินสินค้าเขียนตามเกณฑ์ของเราเอง และการได้รับค่าคอมมิชชันหรือไม่ไม่มีผลต่อลำดับการแนะนำหรือเนื้อหาการประเมิน