【Bash Shell Script】強大的命令提示字元?

BashUnix shell的一種,一般來說Bash就是可以接受用戶輸入命令的程式,包括Linux與MacOSX都將它作為預設shell,它有點類似Windows的命令提示字元,但是功能比較強大,比較像是Windows PowerShell。說了這麼多,為什麼要學bash呢?使用GUI來做事就好了呀?因為有些日常的鎖碎小事,可以利用系統內建的bash就可以處理了,比方說影音轉檔,就可以使用ffmpeg指令,加上迴圈就可以了,其實很多影音轉檔的GUI裡面都是包ffmpeg的。說了這麼多,我們就來慢慢瞭解bash的強大,學習一點簡單的Script吧。

Bash初體驗

建立一個Shell檔

  • 當然只要是『純文字』型的編譯器都可以用來編譯,我這裡就使用VSCode來新建一個.sh檔方便說明,在這裡比較要注意的是檔案的『權限問題』,要使用chmod指令去讓.sh變成有可執行的權限,變更之後,可以看到該檔案的顏色變成『紅色字』,這就表示它可以執行。這點就跟Windons有很大的不同,不是副檔名是『.exe』就是可執行檔,在Linux的世界中,只要該檔案有可執行的『權限』就可以執行,文字檔也可以執行喲,只是…執行不會成功而已…T.T。
#! /bin/bash
echo "hello world"
bash hello.sh
./hello.sh
chmod +x hello.sh
./hello.sh

Bash參數

  • Bash的參數是由『空白』去做為分隔,空白的數量沒有限制,只要是一個空白以上就可以了。
echo "我是一個      參數"
echo 參數1      參數2      參數3

變數

  • 設定。
touch "bash is shell.mp3"
file="bash is shell.mp3"
rm $file
rm "$file"

變數擴展

  • 利用大括弧可以讓變數更有可應用性 ($變數)
User="USER"
echo "$User, $Users, ${User}s"

特殊變數

  • 介紹一些常用的特殊變數
echo "\$0 = $0"
echo "\$1 = $1"
echo "\$2 = $2"
echo "\$# = $#"
echo "\$* = $*"
echo "\$@ = $@"
echo "\$? = $?"
echo "\$$ = $$"
echo "\$! = $!"
echo "\$_ = $_"

數學運算

  • 利用『(())』去做數學運算
i=5
echo $i
((i=i*5))
echo $i

利用指令結果當參數

  • 利用『``/ $()』取得指令的結果
now=`date`
echo $now
time=$(date)
echo $time

Test運算

基本的Test運算

  • Test運算就是指『[…]』,其中要注意的是要加入『空白』,有空白的分隔才會被當成運算使用
[ 1 = 1 ]; echo $?
[ 1 = 2 ]; echo $?

字串判斷

yourname='Kevin Chang' myname='William Weng'
[ $yourname = $myname ]; echo $?
[ "$yourname" = "$myname" ]; echo $?
[ "Kevin Chang" = "William Weng" ]; echo $?

Glob Pattern

echo *
echo *.sh
echo [h]*.sh

if判斷式

if

  • 其實實際上在bash內它只是一行字,所以要注意『空格 / 分號』 (-gt: 大於)
if [ 2 -gt 1 ];
then echo "true";
fi
if [ 2 -gt 1 ]; then echo "true"; fi

if else

if [ 10 -gt 100 ];
then echo "true";
else echo "false";
fi

if elif else

if [ 1 = 2 ]; then 
    echo "true";
elif [ 1 = 3 ]; then
    echo "false";
else
    echo "1 != 2, 1 != 3"
fi

實際範例

if [ -e hello.sh ]; then
    echo "hello.sh 存在";
else 
    echo "hello.sh 不存在";
fi

邏輯運算

  • 『&& / -a』都叫做and,『!』叫not
if [ 1 = 1 ] && [ ! 1 = 2 ]; then
    echo "true";
else
    echo "false";
fi
if [ 1 = 1 -a 2 = 2 ]; then
    echo "true";
else
    echo "false";
fi

四則運算

  • 利用bash做數字的運算
if [ ! $# -eq 3 ]; then
    echo "參數數量不是三個";
    exit;
fi

if [ $2 = "+" ]; then
    echo "相加 = $(($1+$3))";
elif [ $2 = "-" ]; then
    echo "相減 = $(($1-$3))";
else 
    echo "不知道耶"
fi

while迴圈

利用while跑迴圈

(( index=10 ));
while (( index > 0 )); do
    echo "index = $index";
    (( index-- ));
done

利用while讀取csv檔

while read line; do                                         # 一次讀取一行文字
    IFS=',';                                                # 設定分隔號為,
    read -a records <<< "$line";                            # 將line內容存入records中
    echo "${records[0]}, ${records[1]}, ${records[2]}" 
done < $1                                                   # 將檔名(參數1)當成輸入資料

for迴圈

利用for跑迴圈

for index in {10..1}; do
    echo $index;
done

datas="A B C D E";

for string in $datas; do
    echo $string;
done

讀取參數

for paramater in $*; do     # $* => 傳回的是String
    echo $paramater;
done

for paramater in $@; do     # $@ => 傳回的是Array
    echo $paramater;
done

讀取檔案名稱

for filename in *.sh; do
    echo $filename;
done

讀取檔案內容

IFS="\n"
for line in (cat $1); do
    echo $line;
done

switch迴圈

字串比較

  • switch比較要注意的是『)跟;;』的語法
case "$1" in
    william)
        echo "Hello $1";;
    jack)
        echo "Good morning, $1";;
    *)
        echo "How are you, $1";;
esac

數字比較

  • 話說bash的結尾字好像都是『倒著寫』耶?
case "$1" in
    0)
        echo "Zero";;
    1)
        echo "First";;
    *)
        echo "Other";;
esac

select迴圈

字串比較

select filename in *; do
    echo "You select $filename, $REPLY";
    break;
done

select + switch

colors="red green blue"
select color in $colors; do
    case $color in
        "$quit")
            echo "bye"
            break;;
        *)
            echo "selected color is $color";;
    esac
done

function

基本語法

  • 使用function關鍵字或()
function my_print {
    echo "@my_print";
}

your_print () {
    echo "@your_print";
}

my_print;
your_print;

一般函式

hello () {
    echo -e "hello, \$1 = $1, \$2 = $2";
}

isEqual () {
    if [ $1 -eq $2 ]; then
        return 0;
    fi

    return 1;
}

hello william go

isEqual 1 2
echo $?

離開執行

exit_func () {
    if [ $1 = 1 ]; then
        echo "exit in func";
        exit 1;
    fi
}

exit_func $1;
echo "exit in main";
exit 0;

範例程式碼下載

後記

  • 因為個人常常錄製mov,學了一點簡單的bash之後,也不用使用IDE去轉檔,轉成mp4就這麼簡單,三行就OK…這篇只是我的個人筆記而已,學海無涯,各位一起努力吧,加油…
#!/bin/bash
for name in *.mov; do
  ffmpeg -i "$name" -an "${name%.*}.mp4" 
done 
# Windows的可以喲
for /F "delims=" %i in ('dir /b *.mov') do ffmpeg -i "%i" "%~ni.mp4"