Bash commands and Shell script ถ้าไม่รู้ชีวิตจะไม่ง่าย

สารภาพว่าเรื่อง bash commands สำหรับโปรแกรมเมอร์มือใหม่อย่างผม คือเรื่องที่ไม่เคยสนใจเลยจนกระทั่งผมได้เห็น Foreiner programmer คนนึงที่จัดการทุกอย่างแบบ automate ได้อย่างรวดเร็ว ในขณะที่ผมยังทำแบบคลิกทีละจุดอยู่ โอ้ว…ทำไมเราช่างแตกต่างกันแบบนี้ ไม่ได้ล่ะ อยากเทพแบบเขาบ้าง
ทุกอย่างต้องมีจุดเริ่มต้น มาเรียนรู้ไปพร้อมๆกันเลย
Bash command บางคนเรียกว่า ssh หรือ shell เป็นโปรแกรม (Unix shell) ที่ใช้สั่งการคอมพิวเตอร์ให้ทำอะไรบางอย่างผ่าน commands (ssh commands)
เราสามารถดู version ของ bash ได้ด้วยคำสั่ง bash --version
atthana@Atthanas-MacBook-Pro.local:~/Desktop/ $ bash --versionGNU bash, version 3.2.57(1)-release (x86_64-apple-darwin19)
Copyright (C) 2007 Free Software Foundation, Inc.
ปกติ bash or zsh จะติดมากับ Linux, Mac แล้วโดยใช้เรียกผ่าน Terminal, Iterm ได้เลย ส่วนทางฝั่ง windows ต้องใช้ power shell หรือลง Git เพื่อให้ใช้ผ่าน Git bash ได้
สำหรับคนใช้ Mac จะคุ้นเคยกับคำสั่งเหล่านี้อยู่แล้ว ลองดูเล่นๆก่อนคับ


ทีนี้มาดูว่า Top Bash Commands ที่ต้องรู้ มีอะไรบ้าง
1. ls — List directory contents
ls -a
ls -al หรือ ls -la
ls -lta
ls -h#-----------------------
a = all
l = long listing format
t = time (-t to sort by time, newest first)
h = humen readable จะทำให้ file size อ่านง่ายขึ้น

2. echo — Prints text to the terminal window
3. touch — Creates a file
4. mkdir — Create a directory
5. grep — search
grep <text> <file>

จริงๆแล้วยังมี option ให้เล่นอีก เช่น
$ grep -i "two" grassroot.sh # เป็นการค้นหาโดยไม่สนใจว่าจะตัวเล็กหรือตัวใหญ่
keyword i จะเป็นแบบนี้แหละ เหมือนกับ icontain ใน Django# ---------------------------------------------------------$ grep -vi "two" grassroot.sh # เป็นการค้นหาบรรทัดที่ไม่มีคำว่า two
6. man — Print manual or get help for a command
7. pwd — Print working directory
8. cd — Change directory
9. mv — Move or rename directory

10. rmdir — Remove directory
11. locate — Locate a specific file or directory
12. less — view the contents of a text file
13. compgen — Shows all available commands, aliases, and functions
14. > — redirect stdout
ถ้า ‘>’ อันเดียวจะเป็นการ create แบบ replace,
แต่ถ้า ‘>>’ คือมี > สองอันจะเป็นการ create แบบ append
15. cat — Read a file, create a file, and concatenate files
16. | — Pipe ใช้ในการ filter output
เช่น ps ax จะเป็นการแสดง process ที่รันอยู่ทั้งหมด
แต่เราต้องการดูเฉพาะที่มีคำว่า Python เท่านั้นจึงใช้ps ax|grep python
17. head — Read the start of a file
เป็นการ read file จากบรรทัดบนสุดนะ
18. tail — Read the end of a file
เป็นการ read file จากบรรทัดล่างสุดนะ default คือ 10 lines แต่ถ้าต้องการให้มากกว่าหรือน้อยกว่าต้องระบุ option -n
เข้าไป

19. chmod — Sets the file permissions flag on a file or folder
มันย่อมาจาก change mode เพื่อจัดการกับ permission ของไฟล์นั้นๆ เช่น

โดยปกติในพวก file ช่วย authen ที่เป็น private key, public key จะนิยมใช้เป็น
public key = 644
private key = 600


20. exit — Exit out of a directory
21. history — list your most recent commands
22. clear — Clear your terminal window
23. cp — copy files and directories
24. kill — terminate stalled processes
25. sleep — delay a process for a specified amount of time
26. source — เป็นคำสั่งที่ใช้ รัน shell script (.sh)
ซึ่งเราสามารถรันแบบระบุ full path หรือ ถ้าเราอยุ่ใน folder นั้นๆจะรันด้วยวิธีการระบุแบบนี้ ./hello.sh
ก็ได้ เช่น

27. rsync — ใช้สำหรับ sync ไฟล์ระหว่าง 2 directories บน unix
28. cal — อันนี้ลูกเล่นคับ เอาไว้ดูปฎิทินเฉยๆจ้า

29. find — คำสั่งนี้มีประโยชน์มากๆคับ ไว้หา find ว่าอยู่ที่ path ไหน

.yml
นะ
นอกจากการไฟล์จากชื่อแล้ว เราสามารถระบุเงื่อนไข เพื่อนับจำนวนไฟล์ได้ด้วยแบบนี้ (wc -l ก็คือ word count — line
นั่นเอง)
find . -type d| wc -l
สำหรับนับ directoriesfind . -type f | wc -l
สำหรับนับ files

3. find 2024–07–0[1–9] 2024–07–1[0–5] -type f -name “*.pdf” | wc -l
- เป็นการค้นหา folder ทั้งหมดเริ่มตั้งแต่
2024–07–01
ถึง2024–07–15
และนับไฟล์ทั้งหมดที่เป็น.pdf
ว่ามีจำนวนไฟล์เท่าไหร่

4. find 2024–05-{09..31} -type f -name “*.pdf” -delete
- เป็นการหา folder เฉพาะของเดือน 5 ทั้งหมด โดยเลือกเฉพาะไฟล์ที่เป็น pdf เท่านั้น จากนั้นจะลบทิ้งหมดเลย ด้วยคำสั่ง
-delete
ซึ่งต้องระมัดระวังด้วย ถ้าไม่ต้องการdelete
ให้นำคำสั่ง-delete
ออกไปก่อน เพื่อเช็คว่ามีไฟล์จริงไหม
5. sudo find / -type f -exec du -h {} + | sort -rh | head -n 10
find / -type f
ใช้เพื่อหาไฟล์ ตั้งแต่ root เลยนะโดยค้นหาเฉพาะที่เป็น file-exec du -h {} +
คือ ให้ค้นหาขนาดไฟล์ที่อ่านได้ human โดย {} ไว้แทนไฟล์ที่พบนั่นหละ| sort -rh | head -n 10
เอาแค่ 10 ไฟล์แรกที่มีขนาดใหญ่ที่สุด โดยจัดเรียงจากมากไปน้อย-r
และบอกขนาดที่อ่านได้ด้วยh
6. ในการค้นหาทั่วๆไปใน current path สามารถใช้แบบนี้ได้เลย
# เมื่อต้องการหาที่ขึ้นต้นด้วย ... จากนั้นใช้ * แทนส่วนที่เหลือ
find . -name "20221209-1602*"
# เมื่อต้องการค้นหาแบบ specific ไปเลย
find . -name "20221209-160214-850aa215-df14-401d-ac41-89250a4c44f8.pdf"
# maxdepth คำจำกัด folder ปัจจุบันเท่านั้น ไม่ต้องลงไปลึกกว่านั้น
find . -maxdepth 1 -name "20221209-160214-850a215*"
# ค้้นหาว่ามี files หรือ folder ที่ขึ้นต้นด้วยคำว่า 2024
# แล้วทำการรวมขนาดของไฟล์ทั้งหมดออกมาเหลือบรรทัดเดียวแบบนี้ -> (36K total)
find . -maxdepth 1 -name "2024*" -exec du -sch {} + | grep total$
30. unzip — สำหรับ unzip files
- เช่นจากตัวอย่างด้านล่าง เป็นการ unzip all .zip file เพื่อให้รวมกันใน folder
combined
เช่น ในเคสที่ download big file from Google drive it will separate multiple files automatically link.
mkdir combined
unzip '*.zip' -d combined
เรื่องที่ต้องรู้ต่อคือ เราสามารถสร้าง alias ให้เป็น Bash commands ในเครื่องเราเองได้ด้วยคำสั่ง “alias”
Syntax:
alias alias_name = “command_to_run”

เมื่อเราใช้พิมพ์ hello
ก็จะ print grassroot-engineer
ออกมา
ตัวอย่าง used cases คือ ให้ง่ายในการพิมพ์ path ยาวๆที่อาจมีการผิดพลาดได้ เช่น
alias www = ‘python -m SimpleHTTPServer 8000’[ใช้เพื่อสร้าง web server ขึ้นมาใน folder เพียงแค่พิมพ์ www เท่านั้น)-------------------------alias ff = ‘/opt/firefox/firefox’
alias chrome = ‘/opt/google/chrome/chrome’[ใช้เพื่อจดจำ path ที่ยากๆ หลายชึั้น]-------------------------alias name_goes_here = ‘activator && clean && compile && run’[ใช้เพื่อ run คำสั่งแบบ multiple commands ก็ได้]

ต่อไป เราจะมาเรียนรู้ Syntax ที่จะทำให้เราสามารถเขียนโปรแกรมได้ใน shell script
1. Comment:
จะใช้ # เหมือนกับ Python เลยคับ
2. Variables:
เราสามารถประกาศได้เลย โดยไม่ต้องมี data type นำหน้า แต่เมื่อจะเรียกใช้ก็ใช้ $ นำหน้านะคับ … อ่อ ในการ assign ค่าจะต้องไม่มี space คั่นระหว่าง = นะ ไม่งั้นจะ assign ไม่สำเร็จและจะ runtime error
#!/bin/sh # บรรทัดแรกใช้สำหรับ shebangMY_MSG="Hello Grassroot" # ต้องไม่มี space ตอน assign ค่า, string ใช้ ""
echo $MY_MSG # เมื่อจะเรียกใช้ก็ใช้ $ นำหน้า
อีกตัวอย่าง
#!/bin/sh
echo What is your name?
read MY_NAME # read จะเป็น การับค่า input มาเก็บไว้ในตัวแปร MY_NAME
echo "Hello $MY_NAME - hope you're well." # จะ print ค่าที่ได้รับ ออกมา
อีกกรณีในการเรียกใช้ค่าจากตัวแปร เมื่อมีการเชื่อมกับ string ตัวอื่น จะใช้ ${} ครอบตัวแปรหลักของเราไว้

ตัวแปรแบบพิเศษ
เป็นตัวแปรที่ระบบ assign ค่าให้เอง ซึ่งส่วนใหญ่เป็นค่าที่เกี่ยวกับ environment ของ shell script เอง


3. Wildcards (จริงๆแล้ว มันเหมือนกับ RegEx เลยนะ)
เป็นการกำหนดอักขระแทนตัวของกลุ่ม characters เช่น
- ? แทน อักขระใดๆก็ได้หนึ่งตัว ยกเว้นเครื่องหมาย . ในอักขระตัวแรก
- * แทนด้วย อักขระตั้งแต่ 0 ตัวหรือมากกว่านั้น (ทุกตัวนั่นแหละ)
- [] แทนด้วยกลุ่มของตัวอักขระ สามารถใช้ “-” เพื่อกำหนด range. และใช้ “^” เพื่อแยกกลุ่มอักขระนั้นออกไป
ตัวอย่าง:
[abc]??
ชื่อแฟ้มที่ประกอบด้วยอักขระ 3 ตัว ตัวแรกเป็น a หรือ b หรือ c ตัวใดตัวหนึ่ง อีกสองตัวเป็นอักขระอะไรก็ได้อีก 2 ตัว
[1–9][A-Z]
ชื่อแฟ้มที่ประกอบด้วยอักขระ 2 ตัว ตัวแรกเป็นตัวเลขระหว่าง 1–9 (แค่ตัวเดียวนะ)
ตัวที่สองเป็นอักษรตัวใหญ่ (อีกตัวนึง)
[^A-Z]??
ชื่อแฟ้มที่ประกอบด้วยอักขระ 3 ตัว อักขระตัวแรกต้องไม่ใช่อักษรตัวใหญ่ ส่วนอีก 2 ตัวที่เหลือ เป็นอะไรก็ได้
*e[0–9]f
ชื่อแฟ้มที่ลงท้ายด้วยอักษร ‘e’, ตัวเลขในช่วง 0–9 จำนวน 1 ตัว และอักษร ‘f’

4. Loops
มีทั้ง For Loops และ While Loops เหมือนกับภาษา programming ทั่วไปเลยคับ แต่ต่างกันตรงที่ จะตรงมี keyword ‘do’ กับ ‘done’ ใน loop ด้วย
For Loops:

While Loops:
มี syntax แบบนี้ :
while command1 ; # this is loop1, the outer loop
do
Statement(s) to be executed if command1 is true
while command2 ; # this is loop2, the inner loop
do
Statement(s) to be executed if command2 is true
done
Statement(s) to be executed if command1 is true
done

5. If elif else
การใช้งาน if-else ใน shell script จะมี syntax แบบนี้
if [ expression ]; then
commands
elif [ expression ]; then
commands
else
commands
fi

6. Shell Functions
เมื่อเขียน statements ต่างๆได้แล้ว เราจะนำมาสร้างเป็น function ได้ด้วย มี syntax แบบนี้
function_name () {
list of commands
}


ที่นี้หลังจากเรารู้ bash commands แล้ว ก็สามารถทดลองเขียนโปรแกรมด้วย bash ได้ล่ะนะ
$ sleep 5 && echo Q-Electronics.
จากนั้นผ่านไป 5 วินาที ก็จะพ่น Q-Electronics ออกมา
สรุป 5 ขั้นตอนของการสร้าง shell script
1. สร้างไฟล์ grassroot.sh ขึ้นมา
vi grassroot.sh
2. กำหนด interpreter ไว้บรรทัดบนสุด
เพื่อให้โปรแกรมรู้ว่าควรใช้ interpreter ตัวไหนในการโหลดข้อมูล
มี syntax คือ #!<shell program>
ในที่นี้ผมจะใช้ #!/bin/bash
คับ (แต่สามารถใช้ตัวอื่นก็ได้)
สำหรับ comment ใน shell script จะใช้ # เหมือนกับในภาษา Python นะคับ
- #!/bin/sh
- #!/bin/csh
- #!/bin/bash
- #!/bin/ksh
- #!/usr/bin/perl
- #!/usr/bin/env python
#!/bin/bash
3. ใส่ชุดคำสั่ง command line เข้าไปในไฟล์
#!/bin/bashecho 'Grassroot engineer'
4. กำหนดสิทธิ์ให้กับ shell script เพื่อให้ไฟล์นี้สามารถ execute ได้
$ chmod 755 grassroot.sh
5. เรียกใช้งาน shell script (execute) ได้ 3 แบบ คือ
- พิมพ์ full path ของ shell script
- ถ้าอยู่ใน directory ก็ใช้
./<shell script>
ได้เลย - ใช้คำสั่ง source แบบนี้
source grassroot.sh
พอทดลองอ่านมาเรื่อยๆจะพบว่า รายละเอียดค่อนข้างเยอะ มันคือภาษา Programming ภาษานึงเลย
แล้วพบกันใหม่คับ
References:
https://devhints.io/bash
https://www.tutorialspoint.com/unix/if-else-statement.htm
https://www.shellscript.sh/
https://saixiii.com/basic-shell-script/
https://www.educative.io/blog/bash-shell-command-cheat-sheet
https://dev.to/awwsmm/101-bash-commands-and-tips-for-beginners-to-experts-30je
https://nopnithi.medium.com/%E0%B8%AA%E0%B8%A3%E0%B8%B8%E0%B8%9B%E0%B8%84%E0%B8%AD%E0%B8%A3%E0%B9%8C%E0%B8%AA-introduction-to-bash-shell-scripting-%E0%B8%82%E0%B8%AD%E0%B8%87-coursera-75193563ca0a