Bash Cheatsheet - Shell Scripting Command Reference
Most Bash scripts only need a few patterns done right: quoting and ${VAR:-default} guards, $? and test conditions, for/while loops, and functions instead of copy-paste. This table is the subset you actually reach for while writing or fixing scripts — pair it with `set -euo pipefail` and the script stops being fragile.
Typical Use Case
Write scripts, process text and logs, batch rename and find files, compose pipelines on servers, and troubleshoot script permission, unexported variables, and unexpanded globs.
Variables 8
NAME="value"echo $NAMEecho ${NAME}readonly NAME="value"unset NAME${VAR:-default}${VAR:=default}${#VAR}Conditionals 7
if [ condition ]; then ... fiif [ -f file ]; then ... fiif [ $a -eq $b ]; then ... fiif [ "$str" = "value" ]; then ... fiif [[ $str =~ regex ]]; then ... fi[ -d dir ] && echo "exists"case $var in pattern1) ... ;; pattern2) ... ;; esacLoops 6
for i in 1 2 3; do echo $i; donefor ((i=0; i<10; i++)); do ... donewhile [ condition ]; do ... doneuntil [ condition ]; do ... donebreak / continueselect var in list; do ... doneFunctions 7
function name() { ... }name() { ... }name arg1 arg2$1 $2 $@$#return 0local var="value"String Operations 7
${VAR:offset:length}${VAR#pattern}${VAR##pattern}${VAR%pattern}${VAR%%pattern}${VAR/pattern/replacement}${VAR//pattern/replacement}File Tests 8
[ -f file ][ -d dir ][ -e path ][ -r file ][ -w file ][ -x file ][ -s file ][ file1 -nt file2 ]Parameter Expansion & Debugging (REQ-02 add-on) 12
${var:-default}${var:=default}${var:?message}${var#pattern}${var%pattern}${var/pattern/replace}${var^^}${#var}set -xbash -n script.shshopt -s nullglobgetopts "a:b" optParameter matrix
| 参数 | Effect | Example |
|---|---|---|
-x | 执行时打印每条命令,便于调试脚本 | bash -x script.sh |
-e | 命令失败时立即退出脚本 | set -e |
-u | 使用未定义变量时报错 | set -u |
-o pipefail | 管道任一环节失败即视为失败 | set -eo pipefail |
2> | 重定向标准错误 | cmd 2>/dev/null |
| | 管道,前一命令输出作为后一输入 | cat log | grep error | wc -l |
$() | 命令替换,捕获输出 | now=$(date +%F) |
&& / || | 前令成功/失败才执行后令 | make && make install |
-name / -type | find 按名/按类型查找 | find . -name "*.log" -mtime +7 |
-i | 忽略大小写(grep 等) | grep -ri error log/ |
Common pitfalls
Symptom脚本报 Permission denied 无法执行。
Cause文件没有可执行位,或脚本首行 shebang 指向不存在的解释器。
Fixchmod +x script.sh;确认首行 #!/usr/bin/env bash 且 bash 路径存在。
Symptom变量在子 shell/脚本中为空。
Cause未用 export 导出,或作用域仅限当前 shell。
Fix用 export VAR=val 让子进程可见;在脚本内统一用 local/全局变量声明。
Symptomfor f in * 通配符没展开,被当成字面量。
Cause目录为空时 nullglob 未开启,* 保持原样传给命令。
Fix开启 shopt -s nullglob;或用 find ... -print0 | xargs -0 处理空目录情况。
Symptom重定向或管道把文件清空了。
Cause命令如 cat file > file 在读取前先截断目标。
Fix重定向到不同文件或临时文件再覆盖;小心 > 与 >> 的方向。
Symptom空格/特殊字符把文件名拆成多个参数。
Cause未对变量加双引号,IFS 按空格/制表符切割。
Fix始终用 "$var" 包裹变量;处理文件名用 while IFS= read -r line 与 find -print0。
Symptomrm 误删了不该删的文件。
Cause通配符匹配过宽,或路径变量为空。
Fixrm 前先 echo 看匹配结果;危险操作加 -i 确认;避免在变量为空时 rm -rf "$dir"/*。
Troubleshooting
1调试脚本每一步
bash -x script.sh打印实际执行的命令与变量展开,定位逻辑错误。
2确认脚本语法无误
bash -n script.sh只做语法检查不执行,适合上线前校验。
3定位最近修改的大文件
find /var -type f -size +100M -mtime -1排查磁盘突增时快速定位可疑文件。
4统计日志中错误出现次数
grep -ci error /var/log/app.log快速评估错误规模,结合 tail 看最新样例。
Command Examples
Default a possibly-unset variable
NAME=${NAME:-lzh}
echo "$NAME"${var:-default} 在变量未设或为空时取 default;改用 ${var-default} 只在完全未设时才取。
Output
lzh # NAME 未设时输出默认值;已设则输出原值
Test whether a file exists
if [[ -f /etc/nginx.conf ]]; then
echo exists
else
echo missing
fi用 [[ ]] 而非 [ ],支持 && 与 || 且不会错误分词;变量务必用双引号包裹,避免空值时语法报错。
Output
exists
Resolve the directory of the running script
DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
echo "$DIR"用 BASH_SOURCE[0] 而非 $0,这样即使脚本被 source 引入,拿到的也是其真实所在目录。
Output
/home/deploy/scripts
Common Pitfalls
- Prefer [[ ]] and (( )) for tests and arithmetic; [ ] trips on empty variables or strings containing wildcards.
- Quoting variables is a hard rule: for i in $LIST or rm $f without quotes split words or delete the wrong files when spaces or globs are involved.
- set -e means fail fast: a failing line exits instead of continuing. Enable it in important scripts to avoid cascading failures.
- Variables in functions are global by default; forgetting local pollutes globals and setups with the same name are easy to hit.
- Both rm -rf and > redirection really delete or overwrite; echo the command as a preview or guard before running against production data.
Tips
- No spaces around = in variable assignment, or it will be interpreted as a command.
- Always quote variables ("$VAR") to avoid word splitting and special character issues.
- [ ] is syntactic sugar for the test command; [[ ]] is a Bash extension with more features like regex matching.
FAQ
What do set -euo pipefail do respectively at the top of a Bash script?
set -e exits on an error, but a failing command does not trigger the exit when it appears in a condition such as if/while/&&/|| or in the middle of a pipeline; -u makes referencing an undefined variable an error; -o pipefail makes a pipeline return the rightmost non-zero exit code among its commands rather than only the last one. Combined they surface errors early and are the standard for robust scripts.
Why does a variable expand inside double quotes but not single quotes in Bash?
Inside double quotes, $variables, $(commands), and backticks are expanded normally, whereas single quotes treat everything literally with no expansion, which suits paths, regexes, or text that must stay untouched. Always wrap a variable holding a path you want to keep intact in double quotes, or word splitting will break it apart.
What is the difference between $@ and $* in Bash?
Without quoting both are equivalent and split the arguments on whitespace. The decisive difference appears when quoted: the @ form preserves each argument as a separate word, whereas the * form joins all arguments into one string. Prefer the quoted at-sign form when iterating over positional parameters.
How do I read a file line by line in Bash robustly?
Use while IFS= read -r line; do ...; done < file. IFS= prevents stripping leading and trailing whitespace, and -r keeps backslashes literal. Do not use for line in $(cat file), which splits the file into words on whitespace and loses line structure.
How do I check whether the previous command succeeded, and how do I make my script fail on purpose in Bash?
$? holds the exit status of the immediately preceding command, where 0 means success and non-zero means failure, so copy it into a variable before checking. Use exit 1 to exit with a non-zero status deliberately, while exit 0 signals success. Combined with set -e, the script automatically aborts on any uncaught failure.
Official References
Each command links to its official documentation below, so you can verify the latest usage and read deeper.
Maintained by LaoHand
Publicly updated on Sep 10, 2026, continuously proofread against official docs.
Contact Us
Wrong command or description? Send us corrections, business inquiries or product feedback by email.
Contact Us