---
# System prepended metadata

title: 'shell script '

---

:::spoiler shell script 
[toc]
:::

## 1. 文件開頭

在 Shell 腳本中，文件開頭通常以 shebang（#!）開始，指定要用來執行腳本的 Shell 解釋器。這告訴系統該使用哪個解釋器來執行腳本。例如：

```bash
#!/bin/bash
```
這告訴系統使用 Bash 解釋器來執行腳本。

## 2. 註解

註解以 # 符號開頭，可以用來提供腳本的說明、說明代碼功能或添加任何其他有用的信息。例如：

```bash 
# 這是一個 Shell 腳本的例子
# 這個腳本用於打招呼
```

## 3. 變數

在 Shell 腳本中，變量可以使用赋值運算符（=）來賦值。變量的命名不使用特殊字符（如空格），通常使用大寫字母來區分變量名和其他內容。例如：

```bash
name="John"
age=30
```
### 位置參數: 
 `$0`、`$1`、`$2` 等等，分別表示腳本本身的名稱以及傳遞給腳本的參數。
### 特殊變數:
<ul><li><code>$#</code>：參數的個數。</li><li><code>$*</code>：所有參數的列表。</li><li><code>$@</code>：所有參數的列表，每個參數作為一個獨立的單詞。</li><li><code>$?</code>：上一個命令的退出狀態。</li><li><code>$$</code>：當前 shell 的進程 ID。</li></ul>

### 內建變數

在 shell 腳本中，有一些內建的變數可以提供有用的資訊。以下是一些常見的內建變數：

1. `$HOME`：使用者的家目錄路徑。
1. `$PWD`：目前工作目錄的路徑。
1. `$USER`：目前登入系統的使用者名稱。
1. `$SHELL`：目前使用的 shell 程式的名稱。
1. `$PATH`：一個以冒號分隔的目錄列表，用於查找可執行文件。
1. `$RANDOM`：一個隨機數值，範圍從 0 到 32767。
1. `$UID`：目前使用者的數字化識別碼（UID）。
1. `$PPID`：目前執行程序的父程序的進程識別碼（PID）。
1. `$OLDPWD`：前一個工作目錄的路徑。

## 4. 與系統互動
### read 指令：
說明：
read 指令用於從標準輸入中讀取使用者的輸入，並將其儲存在一個變數中。

範例：
```bash
echo "請輸入您的名字："
read name
echo "歡迎您，$name！"
```

### echo 指令：
說明：
echo 指令用於向標準輸出中輸出文本。

範例：
```bash
echo "這是一條消息"
```

### pwd 指令：

說明：
pwd 指令用於顯示目前工作目錄的路徑。

範例：
```bash
current_directory=$(pwd)
echo "目前的工作目錄是：$current_directory"
```

### ls 指令：
說明：
ls 指令用於列出目錄中的檔案和子目錄。

範例：
```bash
echo "目前目錄中的檔案和子目錄："
ls
```

### cp 指令：
說明：
cp 指令用於從一個地方複製檔案到另一個地方。

範例：
```bash
# 將檔案 example.txt 複製到目錄 /tmp 中
cp example.txt /tmp
```

### mv 指令：
說明：
mv 指令用於移動檔案或重新命名檔案。

範例：
```bash
# 將檔案 example.txt 移動到目錄 /tmp 中
mv example.txt /tmp

# 重新命名檔案 example.txt 為 new_example.txt
mv example.txt new_example.txt
```

### rm 指令：
說明：
rm 指令用於刪除檔案。

範例：
```bash
# 刪除檔案 example.txt
rm example.txt
```

###  mkdir 指令：
說明：
mkdir 指令用於創建新的目錄。

範例：
```bash
#創建一個名為 new_directory 的新目錄
mkdir new_directory
```

###  rmdir 指令：
說明：
rmdir 指令用於刪除空目錄。

範例：
```bash
#刪除目錄 empty_directory
rmdir empty_directory
```

###  touch 指令：
說明：
touch 指令用於創建新檔案或更新已存在的檔案的時間戳。

範例：
```bash
#創建一個名為 new_file.txt 的新檔案
touch new_file.txt
```

## 5. 條件句

### if、else、elif指令:
if 指令用於根據條件的真假來執行不同的命令，else 指令用於在 if 條件不滿足時執行命令，而 elif 指令則用於在多個條件之間進行選擇。以下是它們的語法：

<p style="color: red;font-size:30px">!!!注意 [ a 條件 b ] ，方括號 [ ] 前後需要有空格</p>
    
```bash
if [ 條件1 ]; then
    # 如果條件1為 true，執行這裡的命令
elif [ 條件2 ]; then
    # 如果條件2為 true，執行這裡的命令
else
    # 如果以上條件都不滿足，執行這裡的命令
fi
```
* `fi` 表示著 if 條件判斷的結束點

### 邏輯運算:
**OR條件 ⇒[ "\$yn" = "y" ] || [ "\$yn" = "Y" ]**

**AND條件 ⇒[ "\$yn" = "y" ] && [ "\$yn" = "Y" ]**
### 條件指令：
在 shell script 中，條件通常由一個條件表達式來表示，這個表達式會被評估為 true 或 false。以下是一些常見的條件表達式：

* `-e` 文件名：測試文件是否存在。
* `-f` 文件名：測試文件是否存在並且是一個普通文件。
* `-d` 文件名：測試文件是否存在並且是一個目錄。
* `-n` 字符串：測試字符串是否不為空。
* `-z` 字符串：測試字符串是否為空。
* `字符串1 = 字符串2`：測試兩個字符串是否相等。
* `字符串1 != 字符串2`：測試兩個字符串是否不相等。
* `整數1 -eq 整數2`：測試兩個整數是否相等。
* `整數1 -ne 整數2`：測試兩個整數是否不相等。
* `整數1 -gt 整數2`：測試整數1是否大於整數2。
* `整數1 -lt 整數2`：測試整數1是否小於整數2。
* `整數1 -ge 整數2`：測試整數1是否大於或等於整數2。
* `整數1 -le 整數2`：測試整數1是否小於或等於整數2。

範例:
```bash
if [ -f 文件.txt ]; then
    echo "文件存在"
fi

if [ "$USER" = "root" ]; then
    echo "目前用戶是 root"
else
    echo "目前用戶不是 root"
fi
```

## 6. 迴圈

在 Shell 腳本中，可以使用 for 和 while 來進行迭代操作。
### for 迴圈:

for 迴圈可以用來遍歷一個列表中的元素，或者生成一系列數字。

```bash 
for item in 列表; do
    # 在每個元素上執行這裡的命令
done
```

在這裡，列表 可以是一系列的字串、文件名、或者通過 {} 擴展得到的字串。do 表示迴圈開始，done 表示迴圈結束。

範例:
```bash
#!/bin/bash

# 定義一個包含水果名稱的列表
fruits=("apple" "banana" "orange" "grape")

# 使用 for 迴圈遍歷列表中的元素並輸出
echo "遍歷列表中的水果："
for fruit in "${fruits[@]}"; do
    echo "水果：$fruit"
done
```
```bash
#!/bin/bash

# 使用 for 迴圈生成一系列數字
echo "Using for loop to generate a series of numbers:"
for i in {1..5}; do
    echo "Number: $i"
done
```

### while 迴圈:
while 迴圈在條件為 true 時重複執行命令。

```bash
while [ 條件 ]; do
    # 當條件為 true 時執行這裡的命令
done
```

在這裡，[ 條件 ] 是一個表達式，當它為 true 時，迴圈會一直執行。do 表示迴圈開始，done 表示迴圈結束。

範例:
```bash
#!/bin/bash

# 使用 while 迴圈在條件為 true 時重複執行命令
counter=1
echo "Using while loop to print numbers until counter reaches 5:"
while [ $counter -le 5 ]; do
    echo "Number: $counter"
    ((counter++))
done
```

## 7. 函數

可以定義和調用函數，讓代碼更具結構和重用性。例如：

```bash 
greet() {
    echo "Hello, $1!"
}

greet "Alice"
```

## 8. 命令替換

可以使用反引號`` ` ``或 ` $() ` 來執行命令並將其輸出賦值給變量。例如：

```bash
current_date=`date`
# 或者
current_date=$(date)
echo "Current date is $current_date"
```

## 9. 字串操作

在 Shell 腳本中，可以使用一系列的內置命令來操作字符串，包括截取、替換、查找等。例如：

```bash 
# 字符串長度
name="John"
echo "Length of name is ${#name}"

# 字符串截取
str="Hello, World!"
echo "Substring: ${str:7:5}"  # 從第 7 個字符開始，取 5 個字符

# 字符串替換
greeting="Hello, World!"
echo "After replacement: ${greeting/Hello/Hi}"  # 將 "Hello" 替換為 "Hi"

# 查找子字符串
string="This is a test string"
substring="test"
if [[ $string == *"$substring"* ]]; then
    echo "Substring found in string"
fi
```

## 10. 文件操作

Shell 腳本可以用來處理文件，包括創建、讀取、寫入、刪除等操作。例如：

```bash
#!/bin/bash

# 宣告檔案名稱
file_name="example.txt"

# 檢查檔案是否存在
if [ -f "$file_name" ]; then
    echo "檔案已存在"
else
    echo "檔案不存在，正在創建..."
    # 創建檔案
    touch "$file_name"
    echo "檔案已創建"
fi

# 寫入內容到檔案
echo "這是一個範例檔案" > "$file_name"

# 讀取並顯示檔案內容
echo "檔案內容："
cat "$file_name"
```

## 11. 錯誤處理

可以使用 `set -e` 來使腳本在遇到錯誤時立即停止執行。另外，也可以使用 `trap` 命令來設置在收到信號時執行的命令，從而進行錯誤處理。例如：

```bash
#!/bin/bash
set -e

trap 'echo "Error: Script failed"; exit 1' ERR

# 腳本主體
echo "Hello, World!"
```

## 12. 處理命令參數

可以使用特殊變量 $1、$2 等來獲取命令行參數。例如：

```bash 
#!/bin/bash

echo "First argument: $1"
echo "Second argument: $2"
``` 
當你執行腳本時，可以像這樣傳遞參數：
```bash
./script.sh arg1 arg2
```
這樣腳本就可以訪問 $1 和 $2，分別對應到 arg1 和 arg2。

## 13. 綜合常見範例

### 讀取使用者輸入：

```bash
#!/bin/bash

# 提示使用者輸入名字
echo "請輸入您的名字："
read name

# 歡迎訊息
echo "歡迎您，$name！"
```
這個範例會提示使用者輸入名字，然後將其讀取並顯示一條歡迎訊息。


### 取得系統資訊：
```bash 
#!/bin/bash

# 取得系統資訊
echo "系統名稱：$(uname -s)"
echo "系統版本：$(uname -r)"
echo "處理器架構：$(uname -m)"
echo "主機名稱：$(hostname)"
```
這個範例使用了一個名為 uname 的系統命令，以及 hostname 命令，來獲取系統的相關資訊。

### 執行系統命令：
```bash 
#!/bin/bash

# 列出目錄內容
echo "目前目錄內容："
ls

# 顯示磁碟使用情況
echo "磁碟使用情況："
df -h
```
這個範例使用了 ls 命令來列出目前目錄的內容，以及 df 命令來顯示磁碟的使用情況。

### 執行迴圈：
```bash
#!/bin/bash

# 印出數字 1 到 5
echo "印出數字 1 到 5："
for i in {1..5}; do
    echo $i
done
```
這個範例使用了 for 迴圈來印出數字 1 到 5。


