find
การค้นหาไฟล์ในระบบปฏิบัติการลีนุกซ์สามารถทำได้หลายวิธี หนึ่งในคำสั่งที่ได้รับความนิยมคือคำสั่ง find เพราะมีความยืดหยุ่นสูงในการค้นหาไฟล์แต่ละชนิดดังตารางแสดงพารามิเตอร์ (parameter) เพื่อใช้ระบุชนิดไฟล์ที่ต้องการค้นหา
ตารางสัญลักษณ์บอกชนิดไฟล์
ในกรณีที่ต้องการระบุให้ค้นหาเฉพาะไฟล์ทั่วไป (f) หรือ ไดเรกทอรี (d) สามารถใช้ตัวเลือก -type เพื่อระบุประเภทได้ดังตัวอย่างข้างล่าง
Copy $ ls -l
total 28
-rw-r--r-- 1 student student 53 2013-08-21 05:16 error.log
-rwxr-xr-x 1 student student 8497 2013-08-21 06:05 hello
-rw-r--r-- 1 student student 92 2013-08-21 06:05 hello.c
drwxr-xr-x 2 student student 4096 2013-09-17 18:03 out
-rw-r--r-- 1 student student 57 2013-08-21 05:16 result.txt
$ find . -type f
./error.log
./result.txt
./.my_hidden_file
./hello
./hello.c
$ find . -type d
.
./.my_hidden_directory
./out
ในกรณีที่ต้องการค้นหาไฟล์หรือไดเรกทอรีที่ถูกซ่อนอยู่
Copy $ find . -type f -name ".*"
./.my_hidden_file
เนื่องจากระบบไฟล์ภายใต้ระบบปฏิบัติการลีนุกซ์จะเป็นแบบ case sensitive (สนใจตัวพิมพ์เล็ก-พิมพ์ใหญ่) ดังนั้นในการค้นหาไฟล์ที่ใกล้เคียงทั้งหมดโดยไม่สนใจกรณี case sensitive สามารถระบุโดยการใช้ -iname เข้าไปดังตัวอย่างข้างล่าง
Copy $ find -iname "MyProgram.c"
./myprogram.c
./unix/myprogram.c
./programming/MyProgram.c
./MyProgram.c
การระบุระดับความลึกของชั้นไดเรกทอรีในการค้นหา สามารถทำได้โดยการใช้ -mindepth [level] และ -maxdepth [level] ตัวอย่างเช่น ต้องการค้นหาตั้งแต่ไดเรกทอรี root (level 1) และลึกลงไปอีก 2 ชั้น (level 2 - level 3) สามารถใช้คำสั่งดังนี้
Copy $ find / -maxdepth 3 -name shadow
/etc/bash_completion.d/shadow
/etc/shadow
เมื่อต้องการระบุว่าให้ค้นหาไฟล์ที่อยู่เฉพาะระดับความลึกที่ 2 ถึง 4 (level 2 - level 4)
Copy $ find / -mindepth 2 -maxdepth 4 -name shadow
/etc/bash_completion.d/shadow
การค้นหาด้วยคำสั่ง find แต่ละครั้ง สามารถตั้งชุดคำสั่งพิเศษหลังตัวเลือก -exec ในกรณีที่เจอไฟล์ตามที่ต้องการค้นหา ตัวอย่างเช่นให้ทำการเช็คค่า checksum ไฟล์ที่เจอด้วยคำสั่ง md5sum
Copy $ find -iname "MyProgram.c" -exec md5sum {} \;
ed832d42670ee3af4041e4a50f851755 ./myprogram.c
ed832d42670ee3af4041e4a50f851755 ./unix/myprogram.c
7562d93e8b9a19dc80959d4eb7e2c7ca ./programming/MyProgram.c
ae96bf65a87976abba3fdc57f47a55a2 ./MyProgram.c
ถ้าต้องการระบุการค้นหาตามสิทธิ์ของไฟล์นั้น (file permission) สามารถใช้ -perm ได้ดังตัวอย่างข้างล่าง
Copy $ find . -perm -g=r -type f -exec ls -l {} \;
-rw-r--r-- 1 student student 53 2013-08-21 05:16 ./error.log
----r----- 1 student student 57 2013-08-21 05:16 ./result.txt
-rw-r--r-- 1 student student 0 2013-09-17 18:04 ./.my_hidden_file
-rwxr-xr-x 1 student student 8497 2013-08-21 06:05 ./hello
-rw-r--r-- 1 student student 92 2013-08-21 06:05 ./hello.c
$ find . -perm g=r -type f -exec ls -l {} \;
----r----- 1 student student 57 2013-08-21 05:16 ./result.txt
หรือระบุเป็นเลขฐานแปด (Octal)
Copy $ find . -perm 040 -type f -exec ls -l {} \;
----r----- 1 student student 57 2013-08-21 05:16 ./result.txt
งานด้านระบบสมองกลฝังตัวขนาดของไฟล์ข้อมูลค่อนข้างเป็นประเด็นที่ต้องให้ความสนใจ เนื่องจากพื้นที่เก็บข้อมูลมีขนาดจำกัด ดังนั้นการนำคำสั่ง find มาประยุกต์ใช้เพื่อค้นหาไฟล์ตามขนาดไฟล์ที่ต้องการจึงมีความสำคัญเช่นกัน ดังตัวอย่างต่อไปนี้
เมื่อต้องการค้นหาไฟล์ที่มีขนาดใหญ่ 5 อันดับแรก
Copy $ find . -type f -exec ls -s {} \; | sort -n -r | head -5
80 ./testing/ktest/ktest.pl
64 ./perf/util/trace-event-parse.c
64 ./perf/util/symbol.c
60 ./lguest/lguest.c
56 ./perf/util/header.c
หรือขนาดเล็กสุด 5 อันดับแรก แต่ไม่ต้องการรวมไฟล์ที่มีขนาดศูนย์ไบต์ (Empty file)
Copy $ find . -not -empty -type f -exec ls -s {} \; | sort -n | head -5
4 ./firewire/list.h
4 ./firewire/Makefile
4 ./firewire/nosy-dump.h
4 ./include/tools/be_byteshift.h
4 ./include/tools/le_byteshift.h
ในกรณีที่ต้องการระบุขนาดไฟล์ (byte) อย่างชัดเจน สามารถใช้ -size [byte] ดังตัวอย่างข้างล่าง
Copy $ find . -size +200M <------ ไฟล์ที่มีขนาดมากกว่า 200 เมกะไบต์
$ find . -size -200M <------ ไฟล์ที่มีขนาดน้อยกว่า 200 เมกะไบต์
$ find . -size 200M <------ ไฟล์ที่มีขนาด 200 เมกะไบต์
นักพัฒนาสามารถสร้างคำสั่งเฉพาะด้วย alias เพื่อความสะดวกในการค้นหาไฟล์ขนาดที่ต้องการ เพื่อลบทิ้ง ดังตัวอย่างข้างล่าง
Copy $ alias rm50m="find / -type f -name *.tar -size +50M -exec rm -i {} \;"
$ alias rm1g="find / -type f -name *.tar -size +1G -exec rm -i {} \;"
$ alias rm3g="find / -type f -name *.tar -size +3G -exec rm -i {} \;"
$ alias rm5g="find / -type f -name *.tar -size +5G -exec rm -i {} \;"
นอกจากนั้นถ้าต้องการค้นหาไฟล์โดยดูจากเวลาของไฟล์ที่ถูกเข้าถึง (Access time) ถูกเปลี่ยนแปลงข้อมูลภายใน (Modification time) หรือ มีการเปลี่ยนแปลงไอโหนด/สถานะ (Change time) สามารถระบุตัวเลือกดังรายละเอียดในตารางข้างล่าง
ตารางตัวเลือกการเข้าถึงไฟล์ของคำสั่ง find
Copy $ cd unix/
$ vim hello.c <------ แก้ไขข้อมูลภายในไฟล์ hello.c
$ chmod 755 result.txt <------ เปลี่ยนสิทธิ์ของไฟล์ result.txt
ค้นหาไฟล์ภายในไดเรกทอรี unix ที่มีการถูกแก้ไขข้อมูลภายในไฟล์ เมื่อ 10 นาทีที่ผ่านมา
Copy $ find ~/unix/ -mmin -10
/home/student/unix/
/home/student/unix/hello.c
ค้นหาไฟล์ภายในไดเรกทอรี unix ที่มีการถูกเปลี่ยนแปลงสิทธิ์ไฟล์เมื่อ 10 นาทีที่ผ่านมา
Copy $ find ~/unix/ -cmin -10
/home/student/unix/
/home/student/unix/result.txt
/home/student/unix/hello.c
ในกรณีที่ไม่ต้องการให้แสดงผลไฟล์ที่ถูกซ่อน (hidden file) ในผลลัพธ์ของการค้นหา สามารถใช้ -regex ดังตัวอย่างข้างล่าง
Copy $ find ~/unix/ -amin -10 \( ! -regex ".*/\..*" \)
/home/student/unix/
/home/student/unix/hello.c
ในการค้นหาไฟล์ที่ต้องการบางครั้ง ถ้าผู้ใช้ต้องการตั้งเงื่อนไขแยกเป็น 2 ส่วนคือ ตรวจสอบสิทธิ์ และตรวจสอบขนาดไฟล์ สามารถเขียนให้อยู่ในรูปแบบดังตัวอย่างข้างล่าง
Copy $ find / \( -perm -4000 -fprintf ~/unix/suid.txt '%#m %u %p\n' \) , \( -size +100M -fprintf ~/unix/big.txt '%-10s %p\n' \)
$ cat big.txt
510743705 /home/student/aosp/out/host/linux-x86/bin/clang
357304855 /home/student/aosp/out/host/linux-x86/bin/llvm-rs-cc
138665118 /home/student/aosp/out/host/linux-x86/obj/STATIC_LIBRARIES/libclangSema_intermediates/libclangSema.a
138104274 /home/student/aosp/out/host/linux-x86/obj/STATIC_LIBRARIES/libclangStaticAnalyzerCheckers_intermediates/libclangStaticAnalyzerCheckers.a
160314665 /home/student/aosp/out/host/linux-x86/obj/lib/libbcc.so
...
$ cat suid.txt
04755 root /bin/ping6
04755 root /bin/su
04755 root /bin/fusermount
04755 root /bin/umount
04755 root /bin/mount
04755 root /bin/ping
04755 root /usr/bin/chfn
06755 daemon /usr/bin/at
04755 root /usr/bin/lppasswd
04755 root /usr/bin/sudoedit
04755 root /usr/bin/arping
04755 root /usr/bin/gpasswd
...
grep
คำสั่ง grep (Generalized Regular Expression Parser) เป็นคำสั่งที่มีการใช้งานบ่อยครั้งตั้งแต่ระดับคอมพิวเตอร์ตั้งโต๊ะจนไปถึงบอร์ดสมองกลฝังตัวที่มีระบบปฏิบัติการลีนุกซ์อยู่ภายในโดยหน้าที่ของคำสั่งนี้คือการค้นหาข้อความที่อยู่ภายในไฟล์ที่ต้องการตามเงื่อนไขที่ตั้งไว้ ตัวอย่างเช่น
Copy $ grep ".*passwd" suid.txt
04755 root /usr/bin/lppasswd
04755 root /usr/bin/gpasswd
04755 root /usr/bin/passwd
04755 student /home/student/Downloads/poky-dylan-9.0.0/build/tmp/work/i586-poky-linux/shadow/4.1.4.3-r13/package/usr/bin/passwd.shadow
...
ตารางตัวดำเนินการสำหรับคำสั่ง grep
ตัวอย่างการใช้คำสั่ง grep เพื่อค้นหาคำจากผลลัพธ์ของคำสั่ง ls -al
Copy $ ls -al
total 61
drwxr-xr-x 4 student student 4096 2013-09-20 05:09 .
drwxr-xr-x 37 student student 4096 2013-09-11 20:53 ..
-rw-r--r-- 1 student student 5160 2013-09-18 00:04 big.txt
-rw-r--r-- 1 student student 53 2013-08-21 05:16 error.log
-rwxr-xr-x 1 student student 8497 2013-08-21 06:05 hello
-rw-r--r-- 1 student student 93 2013-09-17 19:16 hello.c
drwxr-xr-x 2 student student 4096 2013-09-17 18:04 .my_hidden_directory
-rw-r--r-- 1 student student 0 2013-09-17 18:04 .my_hidden_file
-rw-r--r-- 1 student student 0 2013-09-20 05:09 mytest.txt
-rw-r--r-- 1 student student 72 2013-09-20 05:09 number
-rw-r--r-- 1 student student 0 2013-09-20 04:48 test1.txt
-rw-r--r-- 1 student student 0 2013-09-20 04:48 test.txt
$ ls -al | grep test?.txt
-rw-r--r-- 1 student student 0 2013-09-20 04:48 test1.txt
ในกรณีที่จะใช้ตัวดำเนินการ “+” จำเป็นต้องใช้โปรแกรมรุ่นใหม่ของโปรแกรม grep คือโปรแกรม egrep (Extended Grep) ดังตัวอย่างข้างล่าง
Copy $ ls -al | egrep test+.txt
-rw-r--r-- 1 student student 0 2013-09-20 05:09 mytest.txt
-rw-r--r-- 1 student student 0 2013-09-20 04:48 test.txt
ในกรณีที่ต้องการค้นหาตัวเลขตามจำนวนหลักที่ต้องการ สามารถใช้ตัวดำเนินการ [ ] และ {n} ดังตัวอย่างข้างล่าง
Copy $ cat numbers
ID 3710166
Telephone No. 0891234122
City Code 20131
Phone No. 038191772
$ grep "[0-9]\{5\}$" numbers
City Code 20131
ถ้าต้องการค้นหาที่มีตัวเลขตั้งแต่ 7 หลักขึ้นไปจะใช้ตัวดำเนินการ {m, } ดังตัวอย่างข้างล่าง
Copy $ grep "[0-9]\{7,\}$" numbers
ID 3710166
Telephone No. 0891234122
Phone No. 038191772
การค้นหาข้อมูลภายในไฟล์ log นักพัฒนาสามารถทำการวิเคราะห์เบื้องต้นได้ด้วยตัวดำเนินการ -E ‘pattern1 | pattern2 ’ ดังตัวอย่างของข้อมูล log ข้างล่างนี้
Copy $ cat data.log
1 Station01 Temp_Sensor 35.4
2 Station02 Flow_Sensor 12.4
3 Station03 Light_Sensor 55
4 Station04 Motion_Sensor ON
5 Station05 Current_Sensor 1.42
สามารถใช้คำสั่ง grep เพื่อค้นหาข้อมูลภายในได้ 4 รูปแบบ ได้แก่
Copy (แบบที่ 1) $ grep -i 'station01\|station03' data.log
1 Station01 Temp_Sensor 35.4
3 Station03 Light_Sensor 55
(แบบที่ 2) $ grep -i -E 'station01|station03' data.log
1 Station01 Temp_Sensor 35.4
3 Station03 Light_Sensor 55
(แบบที่ 3) $ grep -i -e station01 -e station03 data.log
1 Station01 Temp_Sensor 35.4
3 Station03 Light_Sensor 55
(แบบที่ 4) $ egrep -i 'station01|station03' data.log
1 Station01 Temp_Sensor 35.4
3 Station03 Light_Sensor 55
เมื่อต้องการค้นหาคำที่อยู่ตำแหน่งต้นบรรทัด จะใช้ “^” นำหน้าคำที่ต้องการค้นหา หรือคำที่อยู่ตำแหน่งปลายบรรทัด จะใช้ “$” ต่อท้ายคำที่ต้องการค้นหา ดังตัวอย่างข้างล่าง
Copy $ grep "^Sep 11" messages.1
Sep 11 21:16:58 EE-Burapha rsyslogd: [origin software="rsyslogd" swVersion="4.2.0" x-pid="691" x-info="
http://www.rsyslog.com
"] rsyslogd was HUPed, type 'lightweight'.
Sep 11 21:44:29 EE-Burapha kernel: [ 3077.192891] e1000: eth0 NIC Link is Down
Sep 11 21:45:17 EE-Burapha kernel: [ 3125.462088] e1000: eth0 NIC Link is Up 1000 Mbps Full Duplex, Flow Control: None
Sep 11 21:46:58 EE-Burapha kernel: [ 3222.009399] e1000: eth0 NIC Link is Down
Sep 11 21:47:04 EE-Burapha kernel: [ 3227.275574] e1000: eth0 NIC Link is Up 1000 Mbps Full Duplex, Flow Control: None
...
$ grep "Link is Down$" messages.1
Sep 11 21:44:29 EE-Burapha kernel: [ 3077.192891] e1000: eth0 NIC Link is Down
Sep 11 21:46:58 EE-Burapha kernel: [ 3222.009399] e1000: eth0 NIC Link is Down
Sep 11 21:47:07 EE-Burapha kernel: [ 3230.682704] e1000: eth0 NIC Link is Down
Sep 11 21:53:34 EE-Burapha kernel: [ 3310.165309] e1000: eth0 NIC Link is Down
Sep 11 21:54:02 EE-Burapha kernel: [ 3338.102673] e1000: eth0 NIC Link is Down
...
การค้นหาคำที่มีอักขระพิเศษอยู่ด้วยนั้น จะต้องใช้ตัวดำเนินการ \ นำหน้าตัวอักขระพิเศษเสมอ ดังตัวอย่างข้างล่าง
Copy $ grep "255\.255\.255\.255" syslog.1
Sep 18 11:36:12 EE-Burapha dhclient: DHCPDISCOVER on eth0 to 255.255.255.255 port 67 interval 3
Sep 18 11:36:13 EE-Burapha dhclient: DHCPREQUEST of 172.16.56.134 on eth0 to 255.255.255.255 port 67
Sep 18 19:54:11 EE-Burapha dhclient: DHCPDISCOVER on eth0 to 255.255.255.255 port 67 interval 3
Sep 18 19:54:12 EE-Burapha dhclient: DHCPREQUEST of 172.16.56.134 on eth0 to 255.255.255.255 port 67
Sep 20 04:50:05 EE-Burapha dhclient: DHCPDISCOVER on eth0 to 255.255.255.255 port 67 interval 5
Sep 20 04:50:06 EE-Burapha dhclient: DHCPREQUEST of 172.16.56.134 on eth0 to 255.255.255.255 port 67
ตารางตัวดำเนินการเพิ่มเติมสำหรับคำสั่ง grep
จากตารางข้างต้น เป็นการระบุตัวอักขระในแต่ละประเภทเพื่อให้การค้นหามีประสิทธิภาพมากขึ้น ดังตัวอย่างการใช้งานดังนี้
Copy $ grep "anacron\[[[:digit:]]\+\]" /var/log/syslog.1
Sep 18 08:50:17 EE-Burapha anacron[27155]: Job `cron.daily' terminated
Sep 18 08:50:17 EE-Burapha anacron[27155]: Job `cron.weekly' started
Sep 18 08:50:17 EE-Burapha anacron[27530]: Updated timestamp for job `cron.weekly' to 2013-09-18
Sep 18 08:50:18 EE-Burapha anacron[27155]: Job `cron.weekly' terminated
...
การรวมคำสั่งเข้าด้วยกัน ด้วยสัญญลักษณ์ที่เรียกว่า Pipe (|) โดยเอาท์พุตของคำสั่งแรกจะเป็นอินพุตของคำสั่งถัดไป จนกระทั่งถึงคำสั่งสุดท้ายที่จะแสดงผลลัพธ์สู่หน้าจอ ดังตัวอย่างการใช้ดังนี้
$ ls <ไดเรกทอรี> | grep <คำค้นหา>
Copy $ ls -al | grep "^d"
drwxr-xr-x 4 student student 4096 2013-09-21 02:21 .
drwxr-xr-x 37 student student 4096 2013-09-11 20:53 ..
drwxr-xr-x 2 student student 4096 2013-09-17 18:04 .hidden_directory
drwxr-xr-x 2 student student 4096 2013-09-17 18:03 out