---
# System prepended metadata

title: bash shell

---

{%hackmd lTq14m8-RK6cksBvQ0Rnrg %}

# Bash Shell

## 常用指令

### cd

切換到某個目錄(ex: nbs2)
```bash=
#!/bin/sh
cd /nbs2
```
如果有cd切換失敗回傳：
```
test.sh: 2: cd: can’t cd to /nbs2
: not found test.sh: ls
```
可能是因為換行格式是採用 Windows ，所以在Linux上會失敗。
可以用以下兩個方式調整：
1. 在 Notepad++ 的工具列，編輯 -> 換行格式 -> 轉換成 UNIX 格式
![image](https://hackmd.io/_uploads/Hk5hGnpna.png)
2. 用 Linux 原生的編輯器編輯，我自己是習慣用 vi。

> Windows換行符號: `\r\n`
> CR（Carriage Return）
> LF（Line Feed）
> Unix換行符號: `\n`

### find

搜尋資料夾底下符合條件的檔案

```bash!
$ find . -name *.exe
# 搜尋所有sh檔案
$ find /home/user/SHELL -type f -name "*.sh" -exec sed -i 's/\r//' {} \;
```

### df

df（磁盤空間使用情況）用於顯示文件系統的磁盤空間使用情況。

* -h：以人類可讀的格式（例如 KB、MB、GB）顯示磁盤空間。
* -T：顯示文件系統類型。

```
[user@1510013NB50 ~]$ df
Filesystem     1K-blocks      Used Available Use% Mounted on    
/dev/sdb       263174212 124391452 125344604  50% /
tools          190786784 167256396  23530388  88% /init
none            13053076         0  13053076   0% /dev
tmpfs               4096         0      4096   0% /sys/fs/cgroup
none            13055508        68  13055440   1% /run
none            13055508         0  13055508   0% /run/lock     
none            13055508        84  13055424   1% /run/shm      
none            13055508         0  13055508   0% /run/user
drivers        190786784 167256396  23530388  88% /usr/lib/wsl/drivers
lib            190786784 167256396  23530388  88% /usr/lib/wsl/lib    
tmpfs           13055508         0  13055508   0% /mnt/wsl
C:\            190786784 167256396  23530388  88% /mnt/c
D:\            783852884 709472912  74379972  91% /mnt/d
tmpfs           13055508         0  13055508   0% /tmp
tmpfs            2611100         8   2611092   1% /run/user/1000      

```


### du

du（磁盤使用量）用於估算文件或目錄的磁盤空間使用量。

* -h：以人類可讀的格式（例如 KB、MB、GB）顯示結果。
* -s：只顯示摘要信息，而不顯示每個子目錄的詳細信息。

```
du -sh /path/to/directory
```

### export

設定環境變數

```bash!
$ export JAVA_HOME=/d/opt/java
```

### ls

檢視目錄中的項目

* -a 顯示所有檔及目錄 (. 開頭的隱藏文件也會列出)
* -d 只列出目錄（不遞迴列出目錄內的檔）。
* -l 以長格式顯示檔和目錄資訊，包括許可權、所有者、大小、創建時間等。
* -r 倒序顯示檔和目錄。
* -t 將按照修改時間排序，最新的檔在最前面。
* -A 同 -a ，但不列出 "." (目前目錄) 及 ".." (父目錄)
* -R 遞迴顯示目錄中的所有檔和子目錄。

```bash!
$ ls
```

### touch

建立新檔案

```bash!
$ touch temp.txt
# 
$ /dev/null > temp.txt
```

### echo

```bash!
$ echo "AAA" > ttt.txt

## 放在最後一行
$ echo "append" >> ttt.txt
```

### rm

### mkdir

建立新資料夾

### cp

複製檔案或資料夾

### pwd

顯示目前路徑

```bash!
$ pwd
/opt/folder
```

> 若在Windows系統中執行pwd的話，可能會顯示Windows路徑`C:\Users\user`，由於此路徑無法在Bash執行，所以需經過轉換

```bash!
$ cygpath.exe -h
Usage: cygpath (-d|-m|-u|-w|-t TYPE) [-f FILE] [OPTION]... NAME...
       cygpath [-c HANDLE] 
       cygpath [-ADHOPSW]
       cygpath [-F ID]

Convert Unix and Windows format paths, or output system path information

Output type options:

  -d, --dos             print DOS (short) form of NAMEs (C:\PROGRA~1\)
  -m, --mixed           like --windows, but with regular slashes (C:/WINNT)
  -M, --mode            report on mode of file (binmode or textmode)
  -u, --unix            (default) print Unix form of NAMEs (/cygdrive/c/winnt)
  -w, --windows         print Windows form of NAMEs (C:\WINNT)
  -t, --type TYPE       print TYPE form: 'dos', 'mixed', 'unix', or 'windows'

$ cygpath -u C:/Users/user
/c/Users/user
```

### grep

包含字眼

```bash!
$ git log --oneline | grep NBS
# 排除master
$ git log --oneline | grep -v master
```

### tail

```bash!
# 同步顯示寫入的資料
$ tail -f /d/opt/application/server.log
#
$ tail -500f /d/opt/application/server.log
```

## 額外延伸學習

### sed

#### 取代換行符號

* -n：沉默模式。
* -e：直接在命令模式編輯。(可不加，請見詳解)
* -f：程式手稿不直接在命列中打上，而是從指定的檔案中載入。
* -i：修改檔案。

```bash!
$ sed -i 's/\r//' shell.sh
```

### awk

文字處理工具

```bash!
$ ls -al 
total 73429
drwxr-xr-x 1 1510013 1049089        0 二月   29 16:08 ./
drwxr-xr-x 1 1510013 1049089        0 二月   27 13:26 ../
drwxr-xr-x 1 1510013 1049089        0 二月   29 14:48 .git/
-rw-r--r-- 1 1510013 1049089     5068 二月   29 14:47 .gitignore
drwxr-xr-x 1 1510013 1049089        0 二月   29 14:47 .vscode/
-rw-r--r-- 1 1510013 1049089  2064054 二月   29 14:27 diff_list.xlsx
drwxr-xr-x 1 1510013 1049089        0 二月   29 14:47 esb-nbs-2015/
drwxr-xr-x 1 1510013 1049089        0 二月   26 17:32 esb-nbs-2015-batch/
drwxr-xr-x 1 1510013 1049089        0 二月   29 14:47 esb-nbs-2015-flows/
drwxr-xr-x 1 1510013 1049089        0 二月   29 14:47 infinity_r8.0/
drwxr-xr-x 1 1510013 1049089        0 二月   29 14:47 infinity-deviceagent/
-rw-r--r-- 1 1510013 1049089     8057 二月   29 14:47 pom.xml
-rw-r--r-- 1 1510013 1049089       56 二月   21 17:26 README.md
drwxr-xr-x 1 1510013 1049089        0 二月   26 15:14 target/
-rw-r--r-- 1 1510013 1049089 73011858 二月   29 14:33 temp.patch

$ ls -al | awk '{print $9}'
./
../
.git/
.gitignore
.vscode/
diff_list.xlsx
esb-nbs-2015/
esb-nbs-2015-batch/
esb-nbs-2015-flows/
infinity_r8.0/
infinity-deviceagent/
pom.xml
README.md
target/
temp.patch
```

### ln

建立短連結

```bash!
$ ln --help
Usage: ln [OPTION]... [-T] TARGET LINK_NAME
  or:  ln [OPTION]... TARGET
  or:  ln [OPTION]... TARGET... DIRECTORY
  or:  ln [OPTION]... -t DIRECTORY TARGET...

$ ln -s /d/opt/test-project link-test-project

$ ls -al
lrwxrwxrwx 1 1510013 1049089       33 十一月  7 17:34 link-test-project -> /d/opt/test-project
```

### 關於變數

```bash
# 若Shell Scirpt的第一行開頭缺少符號"#!"加上所用Shell名稱，執行時可能會遭遇到不可預期的錯誤。
#!/bin/bash
#!/bin/sh
#!/bin/zsh

設定變數方式為
var=value
　
取用變數的方法為
$var

Exmaple 1:
#!/bin/sh
arthur ="我的小名"
echo $arthur
　
 (local)變數的設定，會在在同一個process中持續存在，一直到此process結束。
　
 Shell中，變數的值可以含有space的字串，帶有一個以上space的的變數，給定值的時候，必須以成對的雙引號( " )或單引號(')涵蓋之。
　

 雙引號( " )中若含有變數($var)，會先將變數轉換成其實際的值，單引號(')則會將$var當成是一個值，而不會作轉換動作。

Example 2:
1. echo "arthur就是 $arthur"
2. echo 'arthur就是 $arthur '

結果:
1. arthur 就是 我的小名
2. arthur 就是 $arthur
```

```bash!
#!/bin/bash

var1=He
var2=llo

echo $var1$var2

# Hello

echo ${var1}o$var2

# Heollo

echo "\"$var1$var2\""

# "Hello"
```


## 額外討論

### source


```bash!
$ source /d/opt/exportJAVA.sh
# 另外寫法
$ . /d/opt/exportJAVA.sh
```

### 特殊變數

|變數|說明|
|:--:|:--:|
| $0 |對應 ./test.sh 這個值。如果執行的是 ./work/test.sh， 則對應 ./work/test.sh 這個值，而不是只回傳檔名本身的部分。|
| $1 |會取得 a，即傳入shell的第一個參數。|
| $2 |會取得 b，即傳入shell的第二個參數。|
| $3 |會取得 c，即傳入shell的第三個參數。$4、$5 等參數的含義依此類推。|
| $# |會取得 3，對應傳入shell的參數個數，統計的參數不包括 $0。|
| $@ |會取得 "a" "b" "c"，也就是所有參數的列表，不包括 $0。|
| $* |也會取得 "a" "b" "c"， 其值和 `$@` 相同。但 `$*` 和 `$@` 有所不同。`$*`會把所有參數合併成一個字串，而 `$@` 會得到一個字串參數陣列。|
| $? |可以取得執行 ./test.sh a b c 命令後的回傳值。在執行一個指令後，可以立即用 $? 取得該命令的回傳值。該指令可以是系統自己的指令，也可以是 shell，也可以是自訂的 bash 函數。|

### 影響操作行為的變數

|變數|功能|
|:--:|:--:|
|LANGLC_ALL|語系資料，例如使用 date 輸出資訊時，透過 LANG 可以修改輸出的訊息資料。|
|PATH|	執行檔搜尋的路徑～目錄與目錄中間以冒號(:)分隔，由於執行檔/指令的搜尋是依序由 PATH 的變數內的目錄來查詢，所以，目錄的順序也是重要的。|
|HOME|	代表使用者的家目錄，亦即使用者看到的 ~ 代表的目錄。
|MAIL|	當我們使用 mail 這個指令在收信時，系統會去讀取的郵件信箱檔案 (mailbox)。|
|HISTSIZE|	這個與『歷史命令』有關。我們曾經下達過的指令可以被系統記錄下來，而記錄的『筆數』則是由這個值來設定的。|
|RANDOM|『隨機亂數』的變數。目前大多數的 distributions 都會有亂數產生器，亦即 /dev/random 檔案。讀者可以透過這個亂數檔案相關的變數 ($RANDOM) 來隨機取得亂數。在 BASH 的環境下，RANDOM 變數的內容介於 0~32767 之間，所以，你只要 echo $RANDOM 時，系統就會主動的隨機取出一個介於 0~32767 的數值。|
|PS1|命令提示字元，可使用 man bash 搜尋 PS1關鍵字，即可了解提示字元的設定方式。|
|?|$? 這個變數內容為指令的回傳值，當回傳值為 0 代表指令正常運作結束，當不為 0 則代表指令有錯誤。|

```bash!
$ npm install
npm command not found
$ export PATH=$PATH:/d/opt/nodejs
$ npm install
```

```bash!
[root@localhost ~]$ 
# 修改PS1變數
[root@localhost ~] (This is Cool)
$
```


## 用實作分析

```bash=
#!/bin/sh

js_jar=`find /usr/IBM/WebSphere/AppServer/profiles -name js.jar | head -n 1`
#js_jar=$(find /usr/IBM/WebSphere/AppServer/profiles -name js.jar | head -n 1)
echo "js_jar=${js_jar}"

JAVA_HOME=/usr/java8_64
CLASSPATH=${js_jar}
appPath=`find /usr/IBM/WebSphere/AppServer/profiles -name atcb-coding*jar | ${JAVA_HOME}/bin/java -classpath ${CLASSPATH} org.mozilla.javascript.tools.shell.Main /opt/etabs/tws_shell/getapppath.js`
echo "appPath=${appPath}"

atcb_fotify_a_jar=`find ${appPath} -name fortify-api*jar | head -n 1`
echo "atcb_fotify_a_jar=${atcb_fotify_a_jar}"

atcb_fotify_b_jar=`find ${appPath} -name fortify-fix*.jar | head -n 1`
echo "atcb_fotify_b_jar=${atcb_fotify_b_jar}"

atcb_codingcommon_jar=`find ${appPath} -name b-coding-common-util_etabs*jar | head -n 1`
echo "atcb_codingcommon_jar=${atcb_codingcommon_jar}"

atcb_serveretabs_jar=`find ${appPath} -name b-coding-server_etabs*jar | head -n 1`
echo "atcb_serveretabs_jar=${atcb_serveretabs_jar}"

atcb_serverservice_jar=`find ${appPath} -name b-coding-server-service_etabs*jar | head -n 1`
echo "atcb_serverservice_jar=${atcb_serverservice_jar}"

atcb_serverfunc_jar=`find ${appPath} -name b-coding-server-function_etabs*jar | head -n 1`
echo "atcb_serverfunc_jar=${atcb_serverfunc_jar}"

atcb_coding_jar=`find ${appPath} -name atcb-coding*jar | head -n 1`
echo "atcb_coding_jar=${atcb_coding_jar}"

ibranch_base_m_jar=`find ${appPath} -name ibranch_base_m.jar | head -n 1`
echo "ibranch_base_m_jar=${ibranch_base_m_jar}"

g_base_jar=`find ${appPath} -name g-base.jar | head -n 1`
echo "g_base_jar=${g_base_jar}"

xmlrpc_client_jar=`find ${appPath} -name "xmlrpc-client-3.1.jar" | head -n 1`
echo "xmlrpc_client_jar=${xmlrpc_client_jar}"

xmlrpc_common_jar=`find ${appPath} -name xmlrpc-common-3.1.jar | head -n 1`
echo "xmlrpc_common_jar=${xmlrpc_common_jar}"

commons_httpclient_jar=`find ${appPath} -name commons-httpclient*jar | head -n 1`
echo "commons_httpclient_jar=${commons_httpclient_jar}"

dom4j_jar=`find ${appPath} -name dom4j*jar | head -n 1`
echo "dom4j_jar=${dom4j_jar}"

ws_commons_util_jar=`find ${appPath} -name ws-commons-util*jar | head -n 1`
echo "ws_commons_util_jar=${ws_commons_util_jar}"

log4j_jar=`find ${appPath} -name log4j*jar | head -n 1`
echo "log4j_jar=${log4j_jar}"

commons_logging_jar=`find ${appPath} -name commons-logging*jar | head -n 1`
echo "commons_logging_jar=${commons_logging_jar}"

commons_codec_jar=`find ${appPath} -name commons-codec*jar | head -n 1`
echo "commons_codec_jar=${commons_codec_jar}"

JAVA_HOME=/usr/java8_64
CLASSPATH=${atcb_coding_jar}:${ibranch_base_m_jar}:${g_base_jar}:${xmlrpc_client_jar}:${xmlrpc_common_jar}:${commons_httpclient_jar}:${atcb_serveretabs_jar}:${atcb_serverservice_jar}:${atcb_serverfunc_jar}:${atcb_codingcommon_jar}:${atcb_fotify_a_jar}:${atcb_fotify_b_jar}:${dom4j_jar}:${ws_commons_util_jar}:${log4j_jar}:${commons_logging_jar}:${commons_codec_jar}

${JAVA_HOME}/bin/java -classpath ${CLASSPATH} tw.com.iisi.tcb.utility.TcbScheduleInvokeAgent http://localhost:9080/WebApp/xmlrpc dailyDb /opt/etabs/logs/etabs-schedule.txt 3600000
```
