Bash 命令和運算子
每個 Shell 語言都有其最常使用的命令。 讓我們藉由檢查最常使用的命令,開始建置您的 Bash 作品。
Bash 命令
讓我們查看常見的 Bash 命令,以及其使用方式。
ls
命令
ls
會列出您目前目錄的內容,或命令的引數中所指定目錄的內容。 其會自行列出目前目錄中的所有檔案和目錄:
ls
預設會隱藏名稱開頭為句號的檔案和目錄。 若要在目錄清單中包含這些專案,請使用 -a
旗標:
ls -a
若要取得目前目錄中檔案和目錄的更詳細資訊,請使用 -l
旗標:
ls -l
以下是目錄中的某個範例輸出,其中包含少數 JPEG 和 PNG,以及一個名為 gifs 的子目錄:
-rw-rw-r-- 1 azureuser azureuser 473774 Jun 13 15:38 0001.png
-rw-rw-r-- 1 azureuser azureuser 1557965 Jun 13 14:43 0002.jpg
-rw-rw-r-- 1 azureuser azureuser 473774 Mar 26 09:21 0003.png
-rw-rw-r-- 1 azureuser azureuser 4193680 Jun 13 09:40 0004.jpg
-rw-rw-r-- 1 azureuser azureuser 423325 Jun 10 12:53 0005.jpg
-rw-rw-r-- 1 azureuser azureuser 2278001 Jun 12 04:21 0006.jpg
-rw-rw-r-- 1 azureuser azureuser 1220517 Jun 13 14:44 0007.jpg
drwxrwxr-x 2 azureuser azureuser 4096 Jun 13 20:16 gifs
每一行都會提供對應檔案或目錄的詳細資訊。 該資訊包括指派給其權限、其擁有者、其大小 (以位元組為單位)、上次修改時間,以及檔案或目錄名稱。
cat
命令
假設您想要查看檔案的內容。 您可以為此使用 cat
命令。 除非檔案是文字檔,否則輸出不會有太大的意義。 下列命令會顯示儲存在 /etc 目錄中的 os-release 檔案的內容:
cat /etc/os-release
這是很實用的命令,因為其會告知您正在執行哪個 Linux 發行版本:
NAME="Ubuntu"
VERSION="18.04.2 LTS (Bionic Beaver)"
ID=ubuntu
ID_LIKE=debian
PRETTY_NAME="Ubuntu 18.04.2 LTS"
VERSION_ID="18.04"
HOME_URL="https://www.ubuntu.com/"
SUPPORT_URL="https://help.ubuntu.com/"
BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/"
PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy"
VERSION_CODENAME=bionic
UBUNTU_CODENAME=bionic
/etc 目錄是 Linux 中的特別目錄。 其中包含系統組態檔。 除非您知道您正在做什麼,否則就不會想刪除此目錄中的任何檔案。
sudo
命令
有些 Bash 命令只能由根使用者 (系統管理員或超級使用者) 執行。 如果您嘗試其中一個命令,但沒有足夠的許可權,則會失敗。 例如,只有以超級使用者身分登入的使用者可以使用 cat
來顯示 /etc/at.deny 的內容:
cat /etc/at.deny
at.deny 是一個特殊檔案,能決定誰可以使用其他 Bash 命令來提交作業以供稍後執行。
大多數時候都不建議以根使用者身分執行,這樣過於危險。 若要在不以超級使用者身分登入的情況下,執行需要系統管理權限的命令,請在命令前面加上 sudo
:
sudo cat /etc/at.deny
sudo
代表「由超級使用者執行 (superuser do)」。當您使用該項目時,便是告訴殼層您對此命令是以根使用者層級的權限採取動作。
cd
、mkdir
和 rmdir
命令
cd
代表「變更目錄 (change directory)」,其行為正如名稱所暗示:其會將目前的目錄變更為另一個目錄。 其可讓您從一個目錄移至另一個目錄,就如同其在 Windows 中的對應項目。 下列命令會變更為目前目錄中名為 orders 的子目錄:
cd orders
您可指定 ..
作為目錄名稱來上移一個目錄:
cd ..
此命令會變更為主目錄,也就是您第一次登入時所抵達的目錄:
cd ~
您可以使用 mkdir
命令來建立目錄。 下列命令會在目前的工作目錄中建立名為 orders 的子目錄:
mkdir orders
如果您想使用一個命令來建立子目錄,並在其下建立另一個子目錄,請使用 --parents
旗標:
mkdir --parents orders/2019
rmdir
命令會刪除 (移除) 目錄,但僅限於目錄為空白的情況。 如果並非空白,您反而會收到警告。 幸運的是,您可以使用 rm
命令來刪除與 -r
(遞迴) 旗標結合的非空白目錄。 然後命令會看起來像這樣,rm -r
。
rm
命令
rm
命令是「remove」(移除) 的縮寫。如您所料,rm
會刪除檔案。 所以此命令會終止 0001.jpg:
rm 0001.jpg
而此命令會刪除目前目錄中的所有檔案:
rm *
請小心使用 rm
。 這是危險的命令。
使用 -i
旗標執行 rm
,可讓您在刪除前思考:
rm -i *
養成在每個 rm
命令中包含 -i
的習慣,並可避免成為 Linux 最大錯誤之一的受害者。 可怕的 rm -rf /
命令會刪除整個磁碟機上的每個檔案。 其運作方式是以遞迴方式刪除根目錄及其子目錄的所有子目錄。 -f
(代表「強制 (force)」) 旗標會藉由隱藏提示使問題加重。 別這麼做。
如果您想刪除名為 orders 但不是空的子目錄,可以此方式使用 rm
命令:
rm -r orders
這會刪除 orders 子目錄和其中的所有項目,包括其他子目錄。
cp
命令
cp
命令不只複製檔案,如果您想要,則可複製整個目錄 (和子目錄)。 若要建立 0001.jpg 的複本 (名為 0002.jpg),請使用此命令:
cp 0001.jpg 0002.jpg
如果 0002 .jpg 已經存在,Bash 會以無訊息方式予以取代。 如果您預計這麼做就很好,但如果您不明白將會覆寫舊版本,就沒有那麼好。
幸運的是,如果您使用 -i
(代表「互動式 (interactive)」) 旗標,Bash 會在刪除現有檔案之前警告您。 這樣更安全:
cp -i 0001.jpg 0002.jpg
您可使用萬用字元一次複製數個檔案。 若要將目前目錄中的所有檔案複製到名為 photos 的子目錄,請執行下列動作:
cp * photos
若要將名為 photos 的子目錄中的所有檔案複製到名為 images 的子目錄中,請執行下列動作:
cp photos/* images
這假設 images 目錄已經存在。 如果不存在,您可加以建立「並」 使用此命令來複製 photos 目錄的內容:
cp -r photos images
-r
代表「recursive」(遞徊)。-r
旗標有另一個好處,就是如果 photos 包含自己的子目錄,這些子目錄也會複製到 images 目錄。
ps
命令
ps
命令會提供所有目前執行中程序的快照集。 不需引數,其本身會顯示您所有的殼層程序。也就是說,並不會太多。 但是當您包含 -e
旗標時,情況則不同:
ps -e
-e
會列出「所有」執行中的程序,且通常有許多這類程序。
若要更充分了解系統中有哪些正在執行的程序,請使用 -ef
旗標:
ps -ef
此旗標會顯示所有執行中程序的名稱、其程序識別碼 (PID)、其父系的 PID (PPID),以及其開始時間 (STIME)。 此外,也會顯示其所連結的終端機 (TTY,如果有的話)、已累計的 CPU 時間 (TIME),以及其完整路徑名稱。 以下是簡略的範例:
UID PID PPID C STIME TTY TIME CMD
root 1 0 0 13:35 ? 00:00:03 /sbin/init
root 2 0 0 13:35 ? 00:00:00 [kthreadd]
root 3 2 0 13:35 ? 00:00:00 [rcu_gp]
root 4 2 0 13:35 ? 00:00:00 [rcu_par_gp]
root 5 2 0 13:35 ? 00:00:00 [kworker/0:0-cgr]
root 6 2 0 13:35 ? 00:00:00 [kworker/0:0H-kb]
root 8 2 0 13:35 ? 00:00:00 [mm_percpu_wq]
root 9 2 0 13:35 ? 00:00:01 [ksoftirqd/0]
root 10 2 0 13:35 ? 00:00:02 [rcu_sched]
除此之外,您可能會找到說明以此方式使用 ps
的文件:
ps aux
ps aux
和 ps -ef
相同。 此雙重特性可回溯到 POSIX Unix 系統 (Linux 為其中之一) 與 BSD Unix 系統 (最常見的是 macOS) 之間的歷程差異。 一開始,POSIX 使用了 -ef
,而 BSD 需要 aux
。 目前,這兩個作業系統系列都接受任一格式。
這是絕佳的提醒,提醒您為何應該仔細查看所有 Linux 命令的手冊。 學習 Bash 就如同將英文當作第二種語言學習。 規則有許多例外狀況。
w
命令
使用者來來去去,而有時候您會遇到完全不想遇到的使用者。 當員工離職去追求其他機會時,會呼叫系統管理員,以確保該員工無法再登入公司的電腦系統。 系統管理員也應當要知道已登入的人員,以及不得登入的對象。
為了找出誰在您的伺服器上,Linux 會提供 w
(代表「誰 (who)」) 命令。 其會顯示目前在電腦系統上的使用者以及這些使用者活動的相關資訊。 w
會顯示使用者名稱、其 IP 為止、其登入時間、其目前正在執行的程序,以及這些程序所耗用的時間量。 這是系統管理員的重要工具。
Bash I/O 運算子
您只要執行 Bash 命令及其許多選項,就可以在 Linux 中進行許多動作。 但是當您使用 I/O 運算子結合命令時,可以真的完成工作:
<
用於將輸入重新導向至鍵盤以外的來源>
用於將輸出重新導向至畫面以外的目的地>>
用於執行相同動作,但會附加而不是覆寫|
用於將一個命令的輸出傳送至另一個命令的輸入
假設您想列出目前目錄中的所有項目,但是在名為 listing.txt 的檔案中擷取輸出。 下列命令只會執行該動作:
ls > listing.txt
如果 listing.txt 已經存在,就會遭到覆寫。 如果您改為使用 >>
運算子,則 ls
的輸出會附加至已在 listing.txt中的項目:
ls >> listing.txt
管道運算子很強大 (且經常使用)。 其會將第一個命令的輸出重新導向至第二個命令的輸入。 假設您使用 cat
來顯示大型檔案的內容,但內容的捲動速度太快而無法閱讀。 您可以使用管道將結果輸送到另一個命令 (例如 more
),讓輸出更容易管理。 下列命令會列出目前正在執行的所有程序。 但是螢幕一旦填滿,輸出就會暫停,直到您選取 Enter 以顯示下一行為止:
ps -ef | more
您也可以透過管道將輸出輸送到 head
,只查看前幾行:
ps -ef | head
或者假設您想要篩選輸出,僅限於含有 "daemon" 這個字的輸出行。其中一種做法是透過管道將輸出從 ps
輸送到 Linux 的實用 grep
工具:
ps -ef | grep daemon
輸出看起來像這樣:
azureus+ 52463 50702 0 23:28 pts/0 00:00:00 grep --color=auto deamon
azureuser@bash-vm:~$ ps -ef | grep daemon
root 449 1 0 13:35 ? 00:00:17 /usr/lib/linux-tools/4.18.0-1018-azure/hv_kvp_daemon -n
root 988 1 0 13:35 ? 00:00:00 /usr/lib/accountsservice/accounts-daemon
message+ 1002 1 0 13:35 ? 00:00:00 /usr/bin/dbus-daemon --system --address=systemd: --nofork --nopidfile --systemd-activation --syslog-only
daemon 1035 1 0 13:35 ? 00:00:00 /usr/sbin/atd -f
root 1037 1 0 13:35 ? 00:00:00 /usr/bin/python3 -u /usr/sbin/waagent -daemon
root 1039 1 0 13:35 ? 00:00:00 /usr/lib/linux-tools/4.18.0-1018-azure/hv_vss_daemon -n
azureus+ 52477 50702 0 23:28 pts/0 00:00:00 grep --color=auto daemon
您也可以使用檔案作為輸入。 根據預設,標準輸入來自鍵盤,但也可予以重新導向。 若要從檔案 (而不是鍵盤) 取得輸入,請使用 <
運算子。 其中一個常見的系統管理員工作是將檔案內容排序。 顧名思義,sort
會依字母順序排序文字:
sort < file.txt
若要將已排序的結果儲存到新檔案,您可以將輸入和輸出重新導向:
sort < file.txt > sorted_file.txt
您可以視需要使用 I/O 運算子來鏈結 Linux 命令。 請考慮下列命令:
cat file.txt | fmt | pr | lpr
cat
的輸出會移至 fmt
,fmt
的輸出會移至 pr
,依此類推。 fmt
會將結果格式化為整齊的段落。 pr
將結果分頁。 而 lpr
會將分頁的輸出傳送至印表機。 全都都在單一行中!