Skip to content

Latest commit

 

History

History
1578 lines (1085 loc) · 21.1 KB

File metadata and controls

1578 lines (1085 loc) · 21.1 KB

Shell 基础命令逐词拆解字典

目标:看到一条命令时,能够说明命令名、选项、参数、输入、输出和实际作用。

本文以 Bash、Git Bash 和 WSL 为主。PowerShell 中有些命令名称和行为不同。


0. 先分清:命令、选项和参数

看这条命令:

cp -i dfd.txt dds.txt

逐词拆解:

部分 类型 含义
cp 命令名 执行复制操作
-i 选项 如果目标已经存在,覆盖前先询问
dfd.txt 第一个参数 源文件,也就是从哪里复制
dds.txt 第二个参数 目标文件,也就是复制到哪里

整句话的作用:

把 dfd.txt 的内容复制成一个名为 dds.txt 的文件。
如果 dds.txt 已经存在,覆盖前先询问。

命令格式中的方括号

文档中可能写:

cp [选项] 源 目标

这里的方括号表示“这一部分可以不写”,不是让你真的输入方括号。

所以应该输入:

cp dfd.txt dds.txt

而不是:

cp [dfd.txt] [dds.txt]

注意:文档格式中的 [选项] 和 Bash 判断条件中的 [ -f file ] 不是一回事。


1. pwd:查看当前目录

命令格式:

pwd

逐词拆解:

部分 含义
pwd print working directory,打印当前工作目录

示例:

pwd

可能输出:

/home/alice/project

作用:

告诉你当前终端正位于哪个目录。

什么时候用:

  • 执行 cp、mv、rm 前确认位置。
  • 不知道相对路径从哪里开始时。
  • 脚本运行结果和预期不同时。

2. ls:查看目录内容

命令格式:

ls [选项] [目录或文件]

最简单的例子:

ls

作用:

显示当前目录中的文件和子目录。

指定目录:

ls logs

逐词拆解:

部分 含义
ls 列出内容
logs 要查看的目录

作用:

显示 logs 目录中的内容,但不会进入 logs 目录。

常见选项:

ls -l
ls -a
ls -la
ls -lh
选项 含义
-l 显示详细信息
-a 显示隐藏文件
-h 用 KB、MB 等易读单位显示大小

例子:

ls -lah logs

整句话:

以详细、包含隐藏文件、文件大小易读的方式,显示 logs 目录内容。

3. cd:切换当前目录

命令格式:

cd [目标目录]

例子:

cd logs

逐词拆解:

部分 含义
cd change directory,切换目录
logs 要进入的目标目录

作用:

把当前工作目录切换到 logs。

常见用法:

cd ..    # 返回上一级
cd .     # 保持在当前目录
cd ~     # 回到用户主目录
cd -     # 回到上一次所在目录

含空格的目录:

cd "My Project"

安全写法:

cd "$project_dir" || exit 1

作用:

进入 project_dir 指定的目录;如果进入失败,就退出脚本。

4. mkdir:创建目录

命令格式:

mkdir [选项] 目录名

例子:

mkdir logs

逐词拆解:

部分 含义
mkdir make directory,创建目录
logs 新目录名称

作用:

在当前目录创建一个名为 logs 的目录。

创建多层目录:

mkdir -p project/data/raw
部分 含义
mkdir 创建目录
-p 父目录不存在时一起创建;已经存在时不报错
project/data/raw 要创建的多层路径

作用:

依次创建 project、project/data 和 project/data/raw。
已经存在的部分会保留。

5. touch:创建空文件或更新时间

命令格式:

touch 文件名

例子:

touch hello.txt

逐词拆解:

部分 含义
touch 创建空文件或更新时间
hello.txt 目标文件

作用:

如果 hello.txt 不存在,就创建一个空文件。
如果它已经存在,不删除内容,只更新修改时间。

一次创建多个文件:

touch a.txt b.txt c.txt

注意:PowerShell 默认没有 touch。PowerShell 对应写法:

New-Item hello.txt

6. cp:复制文件或目录

命令格式:

cp [选项] 源 目标

6.1 复制并改名

cp dfd.txt dds.txt

逐词拆解:

部分 角色 含义
cp 命令 copy,复制
dfd.txt 源参数 要复制的原文件
dds.txt 目标参数 新文件的名称或位置

作用:

读取 dfd.txt 的内容,创建或覆盖 dds.txt,
让 dds.txt 拥有与 dfd.txt 相同的内容。
原来的 dfd.txt 仍然保留。

如果原来有:

dfd.txt

执行后通常有:

dfd.txt
dds.txt

6.2 复制到目录

cp dfd.txt backup/

逐词拆解:

部分 含义
cp 复制
dfd.txt 源文件
backup/ 目标目录

作用:

把 dfd.txt 复制到 backup 目录中。
目标文件名仍然是 dfd.txt。

结果:

backup/dfd.txt

6.3 复制目录

cp -r data data-backup
部分 含义
cp 复制
-r recursive,递归复制目录和内部内容
data 源目录
data-backup 目标目录

作用:

把 data 目录以及它里面的所有文件和子目录复制到 data-backup。

常见选项:

选项 含义
-r 递归复制目录
-i 覆盖前询问
-v 显示复制过程
-p 尽量保留时间和权限
-a 归档复制,尽量完整保留属性

安全练习:

cp -iv dfd.txt dds.txt

7. mv:移动或重命名

命令格式:

mv [选项] 源 目标

重命名:

mv old.txt new.txt

逐词拆解:

部分 含义
mv move,移动
old.txt 原文件
new.txt 新名称

作用:

把 old.txt 重命名为 new.txt。
执行后 old.txt 通常不再存在。

移动到目录:

mv report.txt results/

作用:

把 report.txt 移动到 results 目录。
结果路径为 results/report.txt。

与 cp 的区别:

  • cp 复制后源文件保留。
  • mv 移动后原位置不再保留源文件。

安全选项:

mv -iv old.txt new.txt
  • -i:覆盖前询问。
  • -v:显示过程。

8. rm:删除文件或目录

命令格式:

rm [选项] 目标

删除文件:

rm hello.txt

作用:

删除当前目录中的 hello.txt。
通常不会进入回收站。

删除目录:

rm -r old-data
部分 含义
rm remove,删除
-r 递归删除目录内部内容
old-data 要删除的目录

询问后删除:

rm -i hello.txt

删除前建议:

pwd
ls -la
rm -i hello.txt

不要把不理解的路径交给 rm -rf。rm 通常难以恢复。


9. cat:显示或连接文件内容

命令格式:

cat [文件...]

显示文件:

cat app.log
部分 含义
cat 读取并输出文件内容
app.log 要读取的文件

作用:

把 app.log 的全部内容输出到终端。

连接多个文件:

cat part1.txt part2.txt > full.txt

作用:

依次读取 part1.txt 和 part2.txt,
把合并后的内容写入 full.txt。

显示行号:

cat -n app.log

大文件不要直接 cat,优先使用 less。


10. head:查看开头

命令格式:

head [选项] 文件
head app.log

作用:

显示 app.log 的前 10 行。
head -n 5 app.log
部分 含义
head 查看文件开头
-n 5 指定显示 5 行
app.log 输入文件

作用:

显示 app.log 的前 5 行。

11. tail:查看结尾

tail -n 20 app.log

作用:

显示 app.log 的最后 20 行。

持续监控:

tail -f app.log
部分 含义
tail 查看文件结尾
-f follow,文件增加新内容时继续显示
app.log 要监控的文件

使用 Ctrl + C 停止。


12. less:分页阅读文件

less large.log

作用:

分页打开 large.log,不一次把所有内容刷到屏幕。

常用按键:

按键 作用
Space 下一页
b 上一页
/ERROR 向下搜索 ERROR
n 下一个匹配
q 退出

13. echo:输出文字或变量

echo "hello"

作用:

向标准输出打印 hello,并换行。
name="Alice"
echo "Hello, $name"

作用:

先读取变量 name,再打印 Hello, Alice。

写入文件:

echo "hello" > message.txt

作用:

把 hello 写入 message.txt,覆盖旧内容。

14. printf:按指定格式输出

printf '%s\n' "hello"

逐词拆解:

部分 含义
printf 格式化输出命令
%s 放入一个字符串
\n 输出换行
hello 要放进 %s 的值

输出多列:

printf '姓名:%s,数量:%d\n' "Alice" 3
  • %s:字符串。
  • %d:整数。
  • \n:换行。

脚本中需要稳定格式时,printf 通常比 echo 更可靠。


15. grep:搜索包含指定文字的行

命令格式:

grep [选项] 搜索模式 [文件]
grep "ERROR" app.log

逐词拆解:

部分 角色 含义
grep 命令 按行搜索
ERROR 搜索模式 要寻找的文字
app.log 文件参数 在这个文件中搜索

作用:

读取 app.log,只输出包含 ERROR 的行。

常见选项:

grep -n "ERROR" app.log
grep -i "error" app.log
grep -v "ERROR" app.log
grep -c "ERROR" app.log
grep -rn "ERROR" logs/
选项 含义
-n 显示行号
-i 忽略大小写
-v 反向选择,显示不匹配的行
-c 只显示匹配行数量
-r 递归搜索目录

管道例子:

cat app.log | grep "ERROR"

作用:

cat 读取 app.log,把内容通过管道交给 grep,
grep 只留下包含 ERROR 的行。

16. find:查找文件和目录

命令格式:

find 起始目录 [条件]
find . -type f -name "*.log"

逐词拆解:

部分 含义
find 查找路径
. 从当前目录开始
-type f 只匹配普通文件
-name "*.log" 名称匹配所有 .log 文件

作用:

从当前目录开始,递归查找所有扩展名为 .log 的普通文件。

查目录:

find . -type d -name "data"

按修改时间:

find . -type f -mtime -7

作用:

查找最近 7 天修改过的普通文件。

17. wc:统计行、单词和字节

wc app.log

通常输出:

行数 单词数 字节数 文件名

只统计行数:

wc -l app.log

逐词拆解:

部分 含义
wc word count,统计
-l lines,只统计行数
app.log 输入文件

管道统计:

grep "ERROR" app.log | wc -l

作用:

先找出 ERROR 行,再统计这些行有多少条。

18. sort:排序文本行

sort names.txt

作用:

读取 names.txt,按字符顺序排序并输出。
不会自动修改原文件。

数字排序:

sort -n numbers.txt

倒序:

sort -r names.txt

数字倒序:

sort -nr numbers.txt

19. uniq:处理相邻重复行

sort names.txt | uniq

作用:

先排序,让重复行相邻,再由 uniq 合并相邻重复行。

统计重复次数:

sort names.txt | uniq -c

注意:uniq 只比较相邻行,所以通常和 sort 一起使用。


20. cut:按列提取内容

cut -d',' -f1 data.csv

逐词拆解:

部分 含义
cut 从每一行切出指定部分
-d',' 指定逗号为列分隔符
-f1 取第 1 列
data.csv 输入文件

作用:

读取 data.csv 的每一行,用逗号分列,只输出第一列。

取第一列和第三列:

cut -d',' -f1,3 data.csv

21. awk:按列筛选和计算

awk -F',' '{print $1}' data.csv

逐词拆解:

部分 含义
awk 文本按行、按列处理工具
-F',' 指定逗号为列分隔符
{print $1} 对每一行打印第 1 列
data.csv 输入文件

过滤第三列大于 20 的行:

awk -F',' '$3 > 20 {print $0}' data.csv
  • $1:第一列。
  • $2:第二列。
  • $0:整行。
  • NR:当前行号。

跳过标题行:

awk -F',' 'NR > 1 {print $1}' data.csv

22. sed:替换或选取文本

替换输出:

sed 's/old/new/g' file.txt

逐词拆解:

部分 含义
sed 流文本编辑工具
s substitute,替换
old 要寻找的内容
new 替换成的内容
g 一行内所有匹配都替换
file.txt 输入文件

默认只把结果打印到屏幕,不修改原文件。

显示前 10 行:

sed -n '1,10p' file.txt

23. chmod:修改权限

chmod +x run.sh

逐词拆解:

部分 含义
chmod change mode,修改权限
+x 增加执行权限
run.sh 目标文件

作用:

给 run.sh 增加执行权限,使它可以用 ./run.sh 运行。

常见数字权限:

chmod 644 config.txt
chmod 755 run.sh
  • 644:所有者可读写,其他人只读。
  • 755:所有者可读写执行,其他人可读执行。

24. bash、sh 和 ./script.sh

bash script.sh

作用:

明确使用 Bash 解释并执行 script.sh。
脚本不一定需要执行权限。
sh script.sh

作用:

使用 sh 执行脚本。
如果脚本使用 Bash 专属语法,可能失败。
./script.sh

作用:

运行当前目录中的 script.sh。
文件需要执行权限,并依靠第一行 shebang 选择解释器。

25. source:加载另一个脚本

source ./database-common.sh

逐词拆解:

部分 含义
source 在当前 Shell 中读取并执行文件
./database-common.sh 要加载的脚本路径

作用:

执行 database-common.sh,
并让它定义的变量和函数继续存在于当前 Shell。

等价写法:

. ./database-common.sh

这就是公共函数文件常用 source 而不是 bash file.sh 的原因。


26. export:把变量传给子进程

export DB_NAME="app_dev"

逐词拆解:

部分 含义
export 把变量加入环境
DB_NAME 变量名称
app_dev 变量值

作用:

创建 DB_NAME 环境变量。
之后启动的脚本和数据库客户端可以读取它。

查看:

echo "$DB_NAME"
env | grep '^DB_'

27. read:读取用户输入

read -r name

逐词拆解:

部分 含义
read 从标准输入读取一行
-r 不特殊处理反斜杠
name 保存输入的变量名

带提示:

read -r -p "请输入姓名:" name
echo "你好,$name"

读取文件每一行:

while IFS= read -r line; do
    echo "$line"
done < file.txt

28. test、[ ] 和 [[ ]]

[ -f "app.log" ]

作用:

测试 app.log 是否为普通文件。
条件为真返回 0,条件为假返回非 0。

与下面等价:

test -f "app.log"

放进 if:

if [ -f "app.log" ]; then
    echo "文件存在"
fi

双方括号:

if [[ "$name" == "Alice" ]]; then
    echo "名字匹配"
fi

[[ ]] 是 Bash 条件语法,适合模式和复杂判断。


29. command -v、type 和 which

command -v psql

作用:

检查 psql 命令是否存在,并显示它的位置。
type cd

作用:

说明 cd 是内置命令、函数、别名还是外部程序。
which git

作用:

寻找 PATH 中的 git 可执行文件。

脚本中检查依赖时优先使用 command -v:

if ! command -v psql >/dev/null 2>&1; then
    echo "找不到 psql" >&2
    exit 1
fi

30. ps、kill、jobs、fg 和 bg

ps aux

作用:

显示当前系统中的进程信息。
kill 1234

作用:

向进程号 1234 发送终止请求。

后台运行:

long_command &

查看当前终端的后台任务:

jobs

带回前台:

fg

让暂停的任务在后台继续:

bg

31. sleep:等待一段时间

sleep 2

作用:

暂停当前脚本 2 秒,然后继续。
sleep 0.5
sleep 2m
  • 0.5:半秒。
  • 2m:两分钟。

重试脚本中常用于两次连接之间等待。


32. mktemp:创建安全临时文件

tmp_file="$(mktemp)"

逐词拆解:

部分 含义
mktemp 创建名称唯一的临时文件
$(...) 执行命令并取得输出
tmp_file= 把临时路径保存到变量

作用:

创建一个临时文件,并把它的路径保存到 tmp_file。

33. trap:在退出或收到信号时执行动作

trap 'rm -f "$tmp_file"' EXIT

逐词拆解:

部分 含义
trap 注册信号处理动作
rm -f "$tmp_file" 退出时执行的清理命令
EXIT Shell 退出事件

作用:

无论脚本正常完成还是中途失败,退出时都尝试删除临时文件。

34. tee:显示结果并同时写文件

echo "hello" | tee output.txt

逐词拆解:

部分 含义
echo "hello" 产生输入
tee 一份显示,一份写文件
output.txt 输出文件

作用:

屏幕显示 hello,同时把 hello 写入 output.txt。

追加:

echo "next" | tee -a output.txt

35. xargs:把输入变成命令参数

printf "a.txt\nb.txt\n" | xargs ls -l

作用:

把输入的 a.txt 和 b.txt 转换成 ls -l 的参数,
近似执行 ls -l a.txt b.txt。

安全处理带空格文件名:

find . -name "*.log" -print0 | xargs -0 wc -l

36. psql:执行 PostgreSQL 命令

psql "$DB_NAME" -c "SELECT 1;"

逐词拆解:

部分 含义
psql PostgreSQL 命令行客户端
"$DB_NAME" 要连接的数据库名称
-c command,执行后面的 SQL
SELECT 1; 要执行的 SQL

作用:

连接 DB_NAME 指定的 PostgreSQL 数据库,
执行 SELECT 1;,然后退出客户端。

执行 SQL 文件:

psql "$DB_NAME" -f migration.sql
部分 含义
-f file,执行 SQL 文件
migration.sql SQL 文件路径

完整连接参数:

psql \
    --host "$DB_HOST" \
    --port "$DB_PORT" \
    --username "$DB_USER" \
    --dbname "$DB_NAME" \
    --command "SELECT 1;"

37. mysql 和 sqlite3

MySQL:

mysql --host="$DB_HOST" --user="$DB_USER" "$DB_NAME"

作用:

使用指定主机、用户和数据库启动 MySQL 客户端。

执行 SQL:

mysql "$DB_NAME" --execute="SELECT 1;"

SQLite:

sqlite3 app.db "SELECT 1;"

逐词拆解:

部分 含义
sqlite3 SQLite 命令行客户端
app.db 数据库文件
SELECT 1; 要执行的 SQL

38. 管道和重定向逐词拆解

grep "ERROR" app.log | sort | uniq -c > report.txt

逐段拆解:

部分 含义
grep "ERROR" app.log 从日志中选出 ERROR 行
第一个管道 把 ERROR 行交给 sort
sort 排序,让相同行相邻
第二个管道 把排序结果交给 uniq
uniq -c 合并相邻重复行并统计
> report.txt 把最终结果覆盖写入报告

整句话:

从 app.log 找出错误行,排序并统计相同错误出现次数,
最后把统计结果写进 report.txt。

39. 看到陌生命令时怎么分析

按照下面顺序:

  1. 找到第一个词,它通常是命令名。
  2. 找以短横线开头的选项。
  3. 判断剩余参数哪个是输入、哪个是输出。
  4. 看有没有管道。
  5. 看有没有大于号或小于号。
  6. 把变量替换成它当前的真实值。
  7. 把整条命令翻译成一句中文。

例子:

cp -iv "$source_file" "$backup_dir/"

假设:

source_file="app.log"
backup_dir="backup"

先替换变量:

cp -iv "app.log" "backup/"

再翻译:

把 app.log 复制到 backup 目录;
显示复制过程;如果要覆盖已有文件,先询问。

这就是阅读 database-common.sh 时最重要的方法:先替换变量,再逐词拆解,最后翻译成人话。