Linux 采用树状目录结构,根目录为 /,所有文件和目录都从根目录出发:
/├── bin -> usr/bin # 存放二进制命令(ls、cp、mv等常用命令)├── boot # 内核及引导系统程序所在目录├── dev # 所有设备文件的目录(磁盘、光驱等)├── etc # 配置文件默认路径、服务启动命令存放目录├── home # 用户家目录(root用户的家目录为/root)├── lib -> usr/lib # 32位库文件存放目录├── lib64 -> usr/lib64 # 64位库文件存放目录├── media # 媒体文件存放目录├── mnt # 临时挂载设备目录├── opt # 自定义软件安装存放目录├── proc # 进程及内核信息存放目录(虚拟文件系统)├── root # root用户家目录├── run # 系统运行时产生临时文件的存放目录├── sbin -> usr/sbin # 系统管理命令存放目录(仅管理员使用)├── srv # 服务启动后需要访问的数据目录├── sys # 系统使用目录├── tmp # 临时文件目录├── usr # 系统命令和帮助文件目录└── var # 存放内容易变文件的目录(日志、邮件等)
重要目录说明:
/bin | |
/sbin | |
/usr/bin | |
/usr/sbin |
command [-options][parameter]
command | |
[-options] | |
[parameter] |
command--help# 显示命令的帮助信息(简洁版)mancommand# 查阅命令的完整使用手册(manual)
man 手册操作键:
b | |
q | |
/关键词 |
Tab | |
↑ / ↓ | |
Ctrl + C | |
Ctrl + Z | fg/bg 恢复) |
Ctrl + Shift + = | |
Ctrl + - |
ls
ls是list的简写,列出目录内容
ls# 列出当前目录内容ls-a# 显示所有文件,包括隐藏文件(以.开头)ls-l# 以列表方式显示文件详细信息(可简写为 ll)ls-lh# 以列表方式显示,并以人性化方式显示文件大小ls-al# 组合:显示所有文件+详细信息ll # 等同于 ls -l(很多发行版支持)
Linux 文件和目录特点:
. 开头的文件为隐藏文件,需用 -a 参数显示... 代表上一级目录ls 通配符:
* | |
? | |
[abc] | |
[a-f] |
cd
cd是change directory的简写
pwd# 查看当前工作目录(print work directory)cd# 切换到当前用户主目录(/home/用户名)cd ~ # 切换到当前用户主目录cd / # 切换到根目录cd..# 切换到上一级目录cd - # 切换到上一次访问的目录(在两个目录间来回切换)cd /usr/local # 切换到指定绝对路径cd ./aaa # 切换到当前目录下的 aaa 目录(相对路径)
路径说明:
/ 或 ~,相对于当前目录/ 或 ~,从根目录/家目录开始mkdirmkdir aaa # 在当前目录下创建 aaa 目录mkdir ./bbb # 同上(相对路径写法)mkdir /ccc # 在根目录下创建 ccc 目录(绝对路径)mkdir-p temp/nginx # 递归创建多级目录(-p 选项)mkdir{dirA,dirB}# 批量创建多个目录
⚠️ 新建目录名称不能与当前目录中已有的目录或文件同名
treetree # 以树状图显示当前目录结构tree -d# 只显示目录,不显示文件tree /usr/local # 查看指定目录的树状结构tree test01/ # 查看 test01 目录的树状结构
findfind / -name'b'# 从根目录搜索名为 b 的目录和文件find / -name'b*'# 从根目录搜索名以 b 开头的目录和文件find.-name'b'# 从当前目录搜索名为 b 的目录和文件find-name"*.py"# 搜索当前目录下所有 .py 文件(含子目录)find-name"*1*"# 搜索文件名包含 1 的文件find.-name'*.pyc'-execrm-rf{}\;# 递归删除所有 .pyc 文件find.-name"*"-size 145800c -print# 打印当前目录下指定大小的文件find.-type f -name"*.log"# 只搜索文件类型(不包括目录)
mvmv 原名称 新名称 # 重命名(当前目录内)mv tomcat001 tomcat # 将 tomcat001 重命名为 tomcatmv /aaa /bbb # 将根目录下的 aaa 移动到 bbb 目录下mv bbbb usr/bbb # 移动并修改名称为 bbbmv bbb usr/aaa # 移动并修改名称为 aaa
-i选项:覆盖文件前提示确认
cpcp-r /aaa /bbb # 将 /aaa 目录复制到 /bbb 下(保持名称 aaa)cp-r /aa /bbb/aaa # 将 /aa 复制到 /bbb 下,名称改为 aaacp-i 源文件 目标文件 # 覆盖前提示
⚠️ 复制目录必须加
-r选项(递归复制)
rm / rmdirrm-r /bbb # 删除 /bbb 目录(会逐一询问)rm-rf /bbb # 强制删除 /bbb 目录(包含子目录,不提示)rmdir test01 # 删除空目录
⚠️
rm -rf操作不可恢复,使用时务必谨慎!
lnln-s /usr/local/app /data # 创建软链接(类似 Windows 快捷方式)rm-rf /data # 删除软链接(路径末尾不加 /)
注意事项:
-s 建立的是硬链接,工作中几乎不用touchtouch testFile # 创建新文件(文件不存在则创建)touch dirA/{A1,A2,A3}# 在 dirA 目录中批量创建 A1、A2、A3 三个文件
若文件已存在,则修改文件的末次修改时间(不改变内容)
rmrm-r a.java # 删除 a.java(每次询问)rm-rf a.java # 强制删除 a.java(不询问)rm-rf ./a* # 强制删除当前目录下所有以 a 开头的文件rm-rf ./* # 强制删除当前目录下所有文件(极度危险!)
splitsplit-b 10k date.file # 按大小分割(每份10KB,字母后缀)split-b 10k date.file -d-a3# 使用数字后缀,长度为3位split-b 10k date.file -d-a3 split_file # 指定输出文件名前缀split-l10 date.file # 按行数分割(每份10行)
split 参数说明:
-b | |
-l | |
-d | |
-a |
scp# 将本机文件复制到目标服务器scp /home/user/file.txt user@192.168.1.100:/home/user/# 将远程服务器文件复制到本机scp user@192.168.1.100:/home/user/file.txt /home/user/# 复制目录(-r 选项)scp-r demo user@192.168.1.100:Desktop# 指定端口(-P 大写)scp-P2222 01.py user@remote:Desktop/01.py
scp 选项说明:
-r | |
-P |
cat a.java # 查看文件全部内容(适合内容较少的文件)cat-n a.java # 查看文件内容,并对所有行编号cat-b a.java # 查看文件内容,只对非空行编号more a.java # 分屏显示(空格翻页,Enter翻行,q退出)less a.java # 分屏显示,支持上下翻页(PageUp/PageDown),q退出head a.java # 查看文件前10行head-n7 a.java # 查看文件前7行tail a.java # 查看文件后10行tail-n7 a.java # 查看文件后7行tail-f a.java # 实时查看文件末尾新增内容(常用于查看日志)
more 操作键详解:
b | |
f | |
q | |
/word |
more 和 less 的区别:
grep
grep是Global Regular Expression Print的缩写,强大的文本搜索工具
grep"start" test* # 在 test 开头的文件中查找含 start 的行grep under 123.txt # 搜索 under 字符串(大小写敏感)grep-n under 123.txt # 搜索并显示行号grep-v under 123.txt # 显示不包含 under 的行(取反)grep-i under 123.txt # 搜索(忽略大小写)grep-ni under 123.txt # 忽略大小写,并显示行号grep-A1-B1"https" wget-log # 显示匹配行及其前1行(-B)、后1行(-A)grep"^root" /etc/passwd # 搜索以 root 开头的行grep"bash$" /etc/passwd # 搜索以 bash 结尾的行
grep 常用选项:
-n | |
-v | |
-i | |
-A N | |
-B N |
echo'Hello World'> /root/test.txt # 覆盖写入(文件不存在则创建)echo'Hello World'>> /root/test.txt # 追加写入
> | |
>> |
awk功能强大,一次读取一行文本,按分隔符切片后处理
语法:awk [options] 'cmd' file
$1, $2, …($0 表示整行)-F 选项可指定分隔符# 打印第1列和第3列awk'{print $1,$3}' email.out# 当第1列为tcp且第2列为1时,打印整行awk'$1"tcp" && $21 {print $0}' email.out# 打印表头(NR1表示第一行)awk'($1"tcp" && $21) || NR1 {print $0}' email.out# 以逗号为分隔符,打印第2列awk-F","'{print $2}' test.txt# 统计各IP出现次数awk'{count[$1]++} END {for(i in count) print i "\t" count[i]}' access.log# 按逗号切分,将第一列追加到文件awk-F","'{print $1 >> "test01.txt"}' data.txt
sed全名Stream Editor,适合对文本行内容进行批量处理,支持正则表达式
语法:sed [option] 'sed command' filename
sed 常用操作标记:
g | |
p | |
d | |
w | |
s |
# 将以 Str 开头的替换为 String( 表示行首)sed-i's/Str/String/' replace.java# 将行末的 . 替换为 ;(需转义 .)sed-i's/\.$/\;/' replace.java# 全文将 Jack 替换为 me(g 表示全部替换)sed-i's/Jack/me/g' replace.java# 删除空行( *$ 匹配只有空格的行)sed-i'/ *$/d' replace.java# 删除包含 Integer 的行sed-i'/Integer/d' replace.java# 多命令同时执行(用 ; 分隔)grep'input'123.txt |sed's/\"//g; s/,/\n/g'# 替换后保存到新文件sed-n's/\"//gw test01.txt'123.txt
从文件每一行中剪切字段并输出
语法:cut [选项] 文件名
-f | |
-d | \t) |
# 以中文冒号分隔,提取第1列cut-d":"-f1 cut.txt# 以 : 分隔,提取 $PATH 的第3列echo$PATH|cut-d":"-f3# 以 : 分隔,提取第3列及之后所有列echo$PATH|cut-d":"-f3-
|将前一个命令的标准输出作为后一个命令的输入
注意事项:
ls-l|more# 分屏显示 ls 结果ls-l|grep".py"# 在 ls 结果中查找 .py 文件# 从日志中查询包含 error 的行grep'error' email.log# 过滤 error 行中包含数字的部分grep'error' email.log |grep-o'\[0-9\]'# 过滤包含 tomcat 的进程,排除当前 grep 进程ps-ef|grep tomcat |grep-vgrep# 综合管道:提取、切分、替换、保存grep'input'123.txt |awk-F',''{print $2}'|sed's/\"//g'|awk-F":"'{print $1 >> "test01.txt"}'
将标准输入数据转换成命令行参数
# -n:每行输出指定数量cat test.txt |xargs-n3# -d:按指定字符分隔文本echo"nameXnameXnameXname"|xargs-dX# -I:命令替换(每个参数执行一次命令)ls *.jpg |xargs-n1-I{}cp{} /data/images/# -t:将执行的命令也打印出来ls * |xargs-t-n1-I{}cp-r{} /root/backup/# 组合使用:X分隔,每行2个echo"nameXnameXnameXname"|xargs-dX-n2
压缩打包(-c):
tar-cvf start.tar a.java b.java # 将 a.java、b.java 打包tar-cvf start.tar ./* # 将当前目录下所有文件打包tar-zcvf start.tar.gz a.java b.java # 打包并使用 gzip 压缩tar-zcvf start.tar.gz ./* # 将当前目录打包压缩为 .tar.gztar-jcvf start.tar.bz2 ./* # 打包并使用 bzip2 压缩(.tar.bz2)
解压缩(-x):
tar-xvf start.tar # 解包到当前目录tar-xvf start.tar -C /usr/local # 解包到 /usr/local 目录tar-zxvf start.tar.gz # 解压 .tar.gz 到当前目录tar-zxvf start.tar.gz -C /usr/local # 解压 .tar.gz 到指定目录tar-jxvf start.tar.bz2 # 解压 .tar.bz2 到当前目录tar xf node-v12.18.1-linux-x64.tar.xz # 解压 .tar.xz 文件
tar 选项说明:
c | |
x | |
v | |
f | |
-z | |
-j | |
-C |
⚠️ f 选项必须放在选项列表的最后!
压缩(zip):
zip lib.zip tomcat.jar # 压缩单个文件zip-r lib.zip lib/ # 压缩整个目录zip-r lib.zip file1.jar file2.jar # 压缩多个文件
解压缩(unzip):
unzip file1.zip # 解压到当前目录unzip-d /usr/app/ com.example.zip # 解压到指定目录
date# 查看系统当前时间cal# 查看本月日历cal-y# 查看本年日历
df-h# 查看系统各分区磁盘使用情况(human-readable)du-lh# 查看当前目录下各文件夹占用空间du-sh# 查看当前文件夹总占用空间du-h /usr/local # 查看指定目录大小du --max-depth=1# 只查看当前目录下一级的占用情况
ps aux # 查看所有进程详细状态ps-ef|grepjava# 查看名称含 java 的进程ps-ef|grep mysql # 查看 MySQL 相关进程ps-aux|grep28990# 根据 PID 查看进程信息top# 动态实时查看进程资源占用(q 退出)kill-92630# 强制终止 PID 为 2630 的进程
ps 选项说明:
a | |
u | |
x |
top# 实时查看系统资源占用(按 q 退出)
统计信息区说明:
top -15:33:39 up 5:40,2 users, load average:1.09,1.04,0.98Tasks:123 total,3 running,120 sleeping,0 stopped,0 zombie%Cpu(s):42.1 us,2.0 sy,0.0 ni,49.2 id,0.0 wa,6.0 hi,0.7 siKiBMem:3780.9 total,727.4 free,668.8 used,2384.7 buff/cacheKiBSwap:2048.0 total,2046.0 free,2.0 used,859.6 avail
us | |
sy | |
id | |
wa |
进程信息区字段说明:
nohupsh test.sh &# 后台运行,日志输出到 nohup.outnohupsh test.sh >> test.out &# 后台运行,日志输出到 test.out
shutdown-h now # 立即关机shutdown-h10:53 # 在 10:53 关机shutdown-h +10 # 10分钟后自动关机shutdown-r now # 立即重启shutdown-r +30 '30 minutes to reboot'# 30分钟后重启并通知用户shutdown-c# 取消之前的关机/重启计划reboot# 强制重启
-rw-r--r--1 root root 34942Jan192018 bootstrap.jar
权限位说明:- r: read(读取) w: write(写入) x: execute(执行)-: 文件类型(-=普通文件,d=目录,l=软链接)前3位:文件所有者的权限(user)中3位:所属组其他用户的权限(group)后3位:其他用户的权限(others)示例:rw-r--r-- 表示 所有者:可读、可写、不可执行 同组用户:可读、不可写、不可执行 其他用户:可读、不可写、不可执行
chmod# 符号方式chmod u+x web.xml # 给所有者(user)添加执行权限chmod g+x web.xml # 给所属组(group)添加执行权限chmod o+x web.xml # 给其他用户(others)添加执行权限chmod a+x web.xml # 给所有人添加执行权限# 数字方式(r=4, w=2, x=1)chmod755 web.xml # rwxr-xr-x(所有者全权限,其他只读执行)chmod644 web.xml # rw-r--r--(所有者读写,其他只读)chmod777 web.xml # rwxrwxrwx(所有人全权限,生产中慎用)chmod111 web.xml # --x--x--x(所有人只有执行权限)chmod-R755 dir/ # 递归修改目录下所有文件权限
chownchownsum file.txt # 将文件所有者改为 sumchown sum:sum file.txt # 同时改所有者和所属组为 sumchown-Rsum /usr/sum/ # 递归修改目录下所有文件的所有者chown-R sum:sum /usr/sum/ # 递归修改所有者和所属组
# 添加用户useradd-d /usr/sum -msum# 创建用户 sum,家目录为 /usr/sum# 设置用户密码passwdsum# 切换用户su - sum# 切换到 sum 用户(并切换到其家目录)susum# 切换到 sum 用户(保持当前目录)exit# 退出当前登录,回到上一个用户# 查看用户信息idsum# 查看用户 UID 和 GIDwho# 查看当前所有登录用户whoami# 查看当前登录用户账户名cat /etc/passwd # 查看所有用户列表# 修改用户信息usermod 选项 用户名# 删除用户userdelsum# 删除用户rm-rf /usr/sum # 删除用户家目录(需分开执行)# 赋予 root 权限(sudo 权限)visudo # 编辑 sudoers 文件# 在文件中添加:sum ALL=(ALL) ALLsudo-s# 使用 root 权限执行命令
groupadd groupname # 创建用户组groupdel groupname # 删除用户组groupmod-n newname oldname # 将用户组改名chgrp-R groupname dir/ # 递归修改目录所属组cat /etc/group # 查看所有组的信息
ifconfigifconfig# 查看所有网卡配置信息ifconfig|grep inet # 只显示 IP 地址
Linux 物理网卡名通常以 ensXX表示127.0.0.1是本地回环地址,用于测试本机网卡
pingping192.168.1.100 # 持续 ping 目标 IPping-c4 www.example.com # 发送4个 ping 包后停止ping127.0.0.1 # 检测本机网卡是否正常
telnet 49.32.587.164 8093# 检查目标服务器指定端口是否可用lsof-i:8080# 查看占用 8080 端口的进程netstat-tunlp|grep8080# 查看指定端口的进程信息netstat-tunlp# 显示所有 tcp/udp 端口和进程情况netstat-lt# 列出所有处于监听状态的 tcp 端口netstat-an# 查看当前系统的 IP 连接(全平台通用)
查看连接状态数量:
netstat-n|awk'/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}'
sshssh user@192.168.1.100 # 使用默认 22 端口登录ssh-p2222 user@192.168.1.100 # 指定端口号登录exit# 退出 SSH 会话
user | |
remote | |
-p port |
# GET 请求curl"http://www.example.com"# POST 请求(表单格式)curl-d'login=admin&password=123'-X POST https://example.com/login# POST 请求(JSON 格式)curl-l-H"Content-type: application/json"\-X POST \-d'{"phone":"13800138000","password":"test"}'\ http://example.com/api/users
vim /etc/hosts # 编辑 hosts 文件# 添加一行:49.235.32.164 www.example.com/etc/init.d/network restart # 保存后重启网络生效
service iptables status # 查看防火墙状态service iptables stop # 临时关闭防火墙chkconfig iptables off # 设置防火墙开机不启动
yum install iptables-services # 安装软件包yum list # 列出当前已安装的所有包yum search package_name # 在仓库中搜索软件包yum update package_name # 更新指定软件包yum remove package_name # 删除软件包yum clean all # 清除所有缓存# 安装文件传输工具(上传下载)yum install-y lrzszrz # 上传文件到服务器sz filename # 从服务器下载文件
sudoaptinstall 软件包名 # 安装软件sudoapt remove 软件名 # 卸载软件sudoapt upgrade # 更新所有已安装的包sudoapt update # 更新软件包列表
history# 查看历史使用过的命令history|grep es # 过滤与 es 相关的历史命令
cat /etc/redhat-release # 查看操作系统版本(RedHat/CentOS)cat /etc/shells # 查看系统支持的 shell 列表echo$USER# 输出当前用户名echo$PATH# 输出系统路径变量set# 输出所有环境变量whichls# 查看命令所在的位置(如 /bin/ls)whichuseradd# 查看命令路径(如 /usr/sbin/useradd)
crontab-e# 打开/编辑定时任务文件# 示例:每天 0 点执行脚本00 * * * /data/shell/bin/del-30-days-ago-log.sh
crontab 时间格式:
分 时 日 月 周 命令*****/path/to/script.sh
vim /etc/sysctl.conf # 编辑内核参数配置文件sysctl-p# 重新加载配置(不重启生效)
常用系统日志文件位置(以 RedHat/CentOS 为例):
/var/log/messages # 系统启动后的信息和错误日志(最常用)/var/log/secure # 安全相关的日志信息/var/log/maillog # 邮件相关的日志信息/var/log/cron # 定时任务相关的日志/var/log/spooler # UUCP 和 news 设备相关的日志/var/log/boot.log # 守护进程启动和停止的日志# 查看操作历史cat .bash_history # 查看当前用户的命令历史记录
# 搜索镜像docker search mysql# 查看已下载的镜像docker images# 下载并运行容器docker run -di--name=mycontainer -p3306:3306 \-eMYSQL_ROOT_PASSWORD=root <镜像ID># 查看运行中的容器dockerps# 查看所有容器(包括未运行的)dockerps-a# 停止/启动/重启容器docker stop mycontainerdocker start mycontainerdocker restart mycontainer# 删除容器dockerrm mycontainer
vim 是 Linux 系统上最常用的文本编辑器,功能强大。它有三种主要工作模式:
┌─────────────────────────────────────────────────┐│ Vim 三种模式 ││ ││ 普通模式 ──i/a/o──→ 插入模式 ││ ↑ │ ││ └─────── ESC ────────┘ ││ │ ││ └──── : ────→ 命令行模式 ──→ 执行后回普通 │└─────────────────────────────────────────────────┘
vim filename.txt # 打开文件(不存在则创建新文件)vim +3 filename.txt # 打开文件并跳转到第3行vim +/keyword file.txt # 打开文件并定位到第一个关键词处vi filename.txt # vi 是 vim 的精简版
打开文件后默认进入普通模式,不能直接输入文字,主要用于移动光标、复制、删除、搜索等操作。
光标移动:
h | |
l | |
j | |
k | |
w | |
b | |
0 | |
$ | |
gg | |
G | |
nG:n | |
Ctrl+f | |
Ctrl+b |
复制、粘贴、删除:
yy | |
nyy | 3yy) |
p | |
P | |
dd | |
ndd | |
x | |
dw | |
D | |
u | |
Ctrl+r |
搜索:
/keyword | |
?keyword | |
n | |
N |
在普通模式下按以下键进入插入模式(开始输入文字):
i | |
a | |
I | |
A | |
o | |
O |
按
ESC键退出插入模式,返回普通模式
在普通模式下按 : 进入命令行模式(屏幕底部出现 : 提示符):
文件保存与退出:
:w | |
:q | |
:wq | |
:wq! | |
:q! | |
:x | :wq) |
:w filename |
文本替换:
:s/old/new | |
:s/old/new/g | |
:%s/old/new/g | |
:1,5s/old/new/g |
行号与跳转:
:set nu | |
:set nonu | |
:n | :10 跳到第10行) |
其他命令:
:!command | |
:r filename | |
:e filename |
打开文件:vim file.txt ↓ 普通模式(默认) ↓ i / a / o 插入模式(输入文字) ↓ ESC 返回普通模式↓: 命令行模式(保存/退出):wq 保存退出 |:q! 不保存退出
# 快速编辑文件并保存退出vim file.txt # 打开i # 进入插入模式# ... 输入内容 ...ESC # 退出插入模式:wq # 保存退出# 只读查看文件vim-R file.txt # 只读模式打开:q # 查看后退出# 快速替换文本vim file.txt:%s/Jack/Tom/g # 全文替换 Jack 为 Tom:wq # 保存退出
GCC(GNU Compiler Collection)是 Linux 下最常用的 C/C++ 编译器。
# 安装 GCC(CentOS/RedHat)yum install-y gcc# 安装 GCC(Ubuntu/Debian)sudoaptinstall gcc# 查看 GCC 版本gcc --version
源代码(.c)→ 预处理(.i)→ 编译(.s)→ 汇编(.o)→ 链接 → 可执行文件
gcc hello.c -o hello # 编译 hello.c,生成可执行文件 hello./hello # 运行程序
# 第一步:预处理(展开宏定义和头文件,生成 .i 文件)gcc -E hello.c -o hello.i# 第二步:编译(生成汇编代码 .s 文件)gcc -S hello.i -o hello.s# 第三步:汇编(生成目标文件 .o 文件)gcc -c hello.s -o hello.o# 第四步:链接(生成最终可执行文件)gcc hello.o -o hello
# 开启所有警告(推荐初学者使用,帮助发现潜在问题)gcc -Wall hello.c -o hello# 开启调试信息(用于 GDB 调试)gcc -g hello.c -o hello# 指定 C 语言标准gcc -std=c99 hello.c -o hello # 使用 C99 标准gcc -std=c11 hello.c -o hello # 使用 C11 标准# 开启优化gcc -O1 hello.c -o hello # 1级优化gcc -O2 hello.c -o hello # 2级优化(常用)gcc -O3 hello.c -o hello # 3级优化# 链接数学库(使用 math.h 时需要)gcc hello.c -o hello -lm# 同时指定多个源文件gcc main.c utils.c -o program# 指定头文件搜索路径gcc -I /usr/local/include hello.c -o hello# 指定库文件搜索路径gcc hello.c -L /usr/local/lib -lmylib-o hello
1. 编写第一个 C 程序:
vim hello.c # 创建并编辑源文件
在 vim 中输入以下内容:
#include<stdio.h>intmain(){printf("Hello, Linux!\n");return0;}
2. 编译并运行:
gcc hello.c -o hello # 编译./hello # 运行# 输出:Hello, Linux!
目录结构示例:
project/├── main.c├── add.c├── add.h└── Makefile
手动编译多文件:
# 分别编译各源文件为目标文件gcc -c main.c -o main.ogcc -c add.c -o add.o# 链接所有目标文件gcc main.o add.o -o project# 运行./project
一步编译多文件:
gcc main.c add.c -o project
Makefile 可以自动化编译过程,避免每次手动输入编译命令
基本 Makefile 示例(Makefile 文件):
# 目标文件名TARGET = project# C 编译器CC = gcc# 编译选项CFLAGS = -Wall -g# 源文件列表SRCS = main.c add.c# 目标文件列表(.c 替换为 .o)OBJS =$(SRCS:.c=.o)# 默认目标:生成可执行文件$(TARGET):$(OBJS)$(CC)$(OBJS) -o $(TARGET)# 编译每个 .c 文件为 .o 文件%.o: %.c$(CC)$(CFLAGS) -c $< -o $@# 清理编译产生的文件clean: rm -f $(OBJS)$(TARGET)
Makefile 使用命令:
make# 编译项目make clean # 清理编译产生的中间文件和可执行文件make-j4# 使用4个并行任务加速编译
GDB(GNU Debugger)是 Linux 下的 C/C++ 调试工具
# 编译时必须加 -g 选项才能调试gcc -g hello.c -o hello# 启动 GDB 调试gdb ./hello
GDB 常用命令:
run | r | |
break 行号 | b | |
break 函数名 | b | |
next | n | |
step | s | |
print 变量名 | p | |
continue | c | |
list | l | |
quit | q | |
backtrace | bt | |
info locals |
GDB 调试示例:
gdb ./hello(gdb)break main # 在 main 函数设置断点(gdb) run # 开始运行(gdb) next # 执行下一行(gdb) print i # 打印变量 i 的值(gdb)continue# 继续运行(gdb) quit # 退出
No such file or directory | #include 路径或加 -I 参数 | |
undefined reference to 'xxx' | -l 参数 | |
implicit declaration of function | ||
expected ';' before '}' | ||
segmentation fault | ||
warning: unused variable |
pwd | ||
cd ~cd .. / cd - | ||
llls -alh | ||
tree | ||
mkdir -p dir/sub | ||
rmdir dir | ||
rm -rf dir | ||
touch file | ||
cp -r src dst | ||
mv src dst | ||
find -name "*.c" | ||
ln -s src link |
cat -n file | ||
moreless | ||
head -n 10tail -n 10 | ||
tail -f logfile | ||
grep -n pattern file | ||
grep -v pattern file | ||
grep -i pattern file | ||
awk '{print $1}' file | ||
sed 's/old/new/g' file | ||
cut -d "," -f 1 file | ||
cmd > file | ||
cmd >> file | ||
cmd1 | cmd2 |
tar -zcvf out.tar.gz dir/ | |
tar -zxvf file.tar.gz | |
tar -zxvf file.tar.gz -C /dest | |
zip -r out.zip dir/ | |
unzip file.zip -d /dest |
ps aux | |
top | |
kill -9 PID | |
df -h | |
du -sh dir/ | |
shutdown -r now | |
shutdown now | |
date |
chmod 755 file | |
chown user:group file | |
su - username | |
sudo command | |
useradd username | |
passwd username | |
groupadd groupname |
ifconfig | |
ping ip | |
ssh user@host | |
scp file user@host:path | |
netstat -tunlp | |
lsof -i:8080 | |
curl url |
vim file.txt | |
ia(光标后)/ o(下行新增) | |
ESC | |
:wq | |
:q! | |
:%s/old/new/g | |
/keyword?keyword(向上) | |
yynyy(复制n行) | |
ddndd(删除n行) | |
u |
gcc hello.c -o hello | |
gcc -Wall hello.c -o hello | |
gcc -g hello.c -o hello | |
gcc -std=c99 hello.c -o hello | |
./hello | |
make | |
make clean | |
gdb ./hello |
📝 学习建议:
多练习常用命令,熟能生巧 遇到不熟悉的命令,先用 man 命令名或命令 --help查阅文档Vim 的使用需要刻意练习,建议每天使用 vim 编辑文件 C 语言编译建议从单文件开始,逐步过渡到 Makefile 管理多文件项目 在实验环境中大胆尝试各种命令,积累经验
整合自多篇优质博文,涵盖 Linux 日常操作、C 语言编译与 Vim 编辑器使用。
├── bin -> usr/bin # 二进制可执行文件├── boot # 启动相关文件├── dev # 设备文件├── etc # 系统配置文件├── home # 普通用户家目录├── lib -> usr/lib # 库文件├── lib64 -> usr/lib64 # 64位库文件├── media # 挂载媒体设备├── mnt # 临时挂载点├── opt # 第三方软件安装目录├── proc # 进程及内核信息(虚拟文件系统)├── root # root 用户家目录├── run # 运行时数据├── sbin -> usr/sbin # 系统管理命令├── srv # 服务数据├── sys # 内核设备信息├── tmp # 临时文件├── usr # 用户程序和数据└── var # 可变数据(日志、缓存等)
command [-options][parameter]
command[-options]parameter# --help 查看简要帮助ls--help# man 查看详细手册manls# man 中的操作键# 空格:下一页 Enter:下一行 b:回滚一屏# f:前滚一屏 q:退出 /word:搜索
pwd# 查看当前工作目录clear# 清除屏幕cd ~ # 切换到当前用户目录cd / # 切换到根目录cd - # 切换到上一次访问的目录cd..# 切换到上一级目录
ls# 查看当前目录内容(list)ll # 以列表方式查看(ls -l 的别名)ls-a# 显示所有文件,包括隐藏文件ls-l# 以列表方式显示文件详细信息ls-lh# 人性化显示文件大小ls-R# 递归显示子目录# 通配符使用ls *.txt # 所有 .txt 文件ls test? # test 后跟任意一个字符ls[abc]* # 以 a/b/c 开头的文件
mkdir aaa # 创建 aaa 目录mkdir ./bbb # 在当前目录下创建 bbbmkdir /ccc # 在根目录下创建 cccmkdir-p temp/nginx # 递归创建目录# 批量创建mkdir{dirA,dirB}# 同时创建 dirA 和 dirBmkdir dir{1..5}# 创建 dir1 到 dir5# 删除目录rmdir test01 # 删除空目录rm-r test01 # 删除目录(会询问)rm-rf test01 # 强制删除目录(不询问,慎用)
find / -name'b'# 在根目录下查找名为 b 的文件/目录find / -name'b*'# 查找以 b 开头的文件/目录find.-name'*.txt'# 在当前目录查找 .txt 文件find.-name'*.pyc'-execrm-rf{}\;# 查找并递归删除 .pyc 文件find.-name"*"-size 145800c -print# 查找指定大小的文件
# 复制cp-r /aaa /bbb # 复制目录 aaa 到 bbbcp-r /aa /bbb/aaa # 复制并重命名cp-i 源文件 目标文件 # 覆盖前提示# 移动(也用于重命名)mv 源文件 目标文件 # 移动文件/目录mv oldname newname # 重命名mv /aaa /bbb # 将 aaa 移动到 bbb 目录下
tree # 树状图显示目录结构tree -L2# 限制显示层级为 2
touch testFile # 创建空文件(或更新文件时间)touch dirA/{A1,A2,A3}# 批量创建文件rm a.java # 删除文件(会询问)rm-f a.java # 强制删除文件rm-rf ./a* # 强制删除以 a 开头的所有文件rm-rf ./* # 强制删除当前目录所有文件(慎用!)
# 创建软链接(类似 Windows 快捷方式)ln-s /usr/local/app /data# 删除软链接(注意:最后不要加 /)rm-rf /data# 创建硬链接(不常用)ln 源文件 链接文件# 区别:软链接是快捷方式,硬链接是文件的另一个入口# 硬链接数 = 0 时文件才被真正删除
# 按大小拆分(10KB)split-b 10k date.file# 使用数字后缀split-b 10k -d date.file# 指定前缀split-b 10k date.file split_file# 按行数拆分(每10行)split-l10 date.file
cat a.java # 查看文件全部内容(适合小文件)cat-n a.java # 显示行号cat-b a.java # 对非空行编号more a.java # 分页查看(只能向下翻)less a.java # 分页查看(可上下翻页,推荐)# more 与 less 的区别:# 1. less 支持上下方向键翻页,more 不支持# 2. less 加载速度更快# 3. less 退出后不残留内容,more 会残留# 4. more 不能后退head a.java # 查看前10行head-n7 a.java # 查看前7行tail a.java # 查看后10行tail-n7 a.java # 查看后7行tail-f a.java # 实时查看文件末尾(常用于查看日志)
# 重定向(覆盖写入)echo'Hello World'> /root/test.txtls-l> file_list.txt# 重定向(追加写入)echo'Another line'>> /root/test.txt# 管道(前一个命令的输出作为后一个命令的输入)ps-ef|grepjavacat /etc/passwd |grep'root'find ~ |grep"test"
grep[options] pattern filegrep under 123.txt # 搜索包含 under 的行grep-n under 123.txt # 显示行号grep-v under 123.txt # 反向搜索(不包含 under 的行)grep-i under 123.txt # 忽略大小写grep-ni under 123.txt # 组合:行号 + 忽略大小写grep"start" test* # 在 test 开头的文件中搜索grep-A1-B1"https"file# 显示匹配行的前1行和后1行# 正则模式grep'^a'file# 以 a 开头的行grep'ke$'file# 以 ke 结尾的行
awk[options]'cmd'file# 基本用法:$0 整行,$1 第一列,$2 第二列...awk'{print $1,$3}'file# 打印第1列和第3列awk-F","'{print $2}' test.txt # 以逗号分隔,打印第2列# 条件筛选awk'$1"tcp" && $21{print $0}'file# 条件匹配awk'($1"tcp")|| NR1 {print $0}'file# 包含表头# 统计awk'{count[$1]++} END {for(i in count) print i "\t" count[i]}'file# 输出到文件awk-F","'{print $1 >> "test01.txt"}'file
sed[option]'sed command' filename# 替换(s/原内容/新内容/)sed-i's/Str/String/' replace.java # 替换行首 Str 为 Stringsed-i's/\.$/;/'file# 将末尾 . 替换为 ;sed-i's/Jack/me/g' replace.java # 全局替换 Jack 为 me# 删除sed-i'/ *$/d' replace.java # 删除空行sed-i'/Integer/d' replace.java # 删除包含 Integer 的行# 多命令grep'input'123.txt |sed's/"//g; s/,/\n/g'# 替换后存入文件sed-n's/"//gw test01.txt'file
cut-f 列号 -d 分隔符 filecut-f1-d':' /etc/passwd # 以 : 分隔,取第1列cat /etc/passwd |cut-d':'-f1,3# 取第1列和第3列
cat test.txt |xargs-n3# 每行输出3个字段echo"nameXnameXnameXname"|xargs-dX# 按 X 分隔ls *.jpg |xargs-n1-I{}cp{} /data/images # 批量复制
# 打包tar-cvf start.tar a.java b.java # 打包指定文件tar-cvf start.tar ./* # 打包当前目录所有文件# 解包tar-xvf start.tar # 解包到当前目录tar-xvf start.tar -C /usr/local # 解包到指定目录# 压缩(gzip,.tar.gz)tar-zcvf start.tar.gz a.java b.java # 打包并压缩tar-zxvf start.tar.gz # 解压到当前目录tar-zxvf start.tar.gz -C /usr/local # 解压到指定目录# 压缩(bzip2,.tar.bz2)tar-jcvf start.tar.bz2 a.java # 打包并压缩tar-jxvf start.tar.bz2 # 解压# 解压 .tar.xztar-xf node-v12.18.1-linux-x64.tar.xz
tar 选项说明:
# 压缩zip lib.zip tomcat.jar # 压缩单个文件zip-r lib.zip lib/ # 压缩目录zip-r lib.zip a.jar b.jar # 压缩多个文件# 解压unzip file1.zip # 解压unzip-d /usr/app/ file.zip # 解压到指定目录
-rw-r--r--1 root root 34942Jan192018 bootstrap.jar||||||| └── 其他用户权限:r--(只读)|| └──── 组用户权限:r--(只读)| └─────── 文件所有者权限:rw-(读写)└────────── 文件类型:- 文件 / d 目录 / l 链接r =Read(4), w =Write(2), x = eXecute(1)
# 字母方式chmod u+x web.xml # 所有者添加执行权限chmod g+x web.xml # 所属组添加执行权限chmod o+x web.xml # 其他用户添加执行权限chmod u-w web.xml # 所有者移除写入权限# 数字方式chmod755file# rwxr-xr-x(所有者全权限,其他只读执行)chmod644file# rw-r--r--(所有者读写,其他只读)chmod777file# rwxrwxrwx(所有人全权限,不安全)# 递归修改chmod-R755 dir/
chown 用户名 文件名 # 修改文件所有者chown 用户名:组名 文件名 # 同时修改所有者和组chown-R 用户名:组名 目录/ # 递归修改
# 添加用户useradd-d /home/sum -msum# 创建用户并指定家目录useradd-u1001-g group1 sum# 指定 UID 和默认组# 设置密码passwdsum# 切换用户susum# 切换到 sum 用户su - sum# 切换用户并切换到家目录exit# 退出当前用户# 查看用户信息idsum# 查看 UID 和 GIDwho# 查看当前登录用户whoami# 查看当前用户名cat /etc/passwd # 查看所有用户信息# 修改用户usermod-g 组名 用户名 # 修改用户默认组usermod-d /new/home 用户名 # 修改用户家目录# 删除用户userdelsum# 删除用户(保留家目录)userdel-rsum# 删除用户及家目录
cat /etc/group # 查看所有组信息groupadd groupname # 添加组groupmod-n newname oldname # 修改组名groupdel groupname # 删除组
# 编辑 sudoers 文件visudo# 添加如下行(给用户 root 权限)# sum ALL=(ALL) ALL# 使用 sudo 执行命令sudo 命令sudo-s# 切换到 root 用户
date# 查看系统日期时间date"+%Y-%m-%d %H:%M:%S"# 格式化输出cal# 查看当月日历cal-y# 查看全年日历cat /etc/redhat-release # 查看系统版本uname-a# 查看内核版本# 磁盘信息df-h# 查看磁盘剩余空间du-sh# 查看当前目录占用空间du-lh# 查看各文件夹占用空间du --max-depth=1# 只查看当前目录下文件占用空间# 环境变量echo$PATH# 查看 PATH 变量echo$USER# 输出某个变量set# 输出所有变量
ps aux # 查看所有进程详情ps-ef|grepjava# 查看 java 相关进程top# 实时动态显示进程(按 q 退出)# 结束进程kill PID # 终止指定进程kill-9 PID # 强制终止进程# 后台运行nohupsh test.sh &# 后台运行,日志输出到 nohup.outnohupsh test.sh >> test.out &# 后台运行,指定日志文件# Ctrl+Z vs Ctrl+C# Ctrl+Z:挂起进程(可用 fg 恢复前台,bg 转到后台)# Ctrl+C:强制中断进程
# 网卡信息ifconfig# 查看网卡配置(新版可用 ip addr)ifconfig|grep inet # 查看 IP 地址ip addr # 新版命令# 网络连通性ping127.0.0.1 # 测试本机网卡ping-c4 www.example.com # 发送 4 个包后停止# 端口与连接netstat-an# 查看所有连接netstat-tunlp# 查看 TCP/UDP 端口及进程netstat-tunlp|grep8080# 查看指定端口占用lsof-i:8080# 查看端口被哪个进程占用# 查看连接状态统计netstat-n|awk'/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}'# telnet 测试端口telnet IP 端口 # 测试远程端口是否可达
# 远程登录ssh user@remote # 默认端口22ssh-p2222 user@remote # 指定端口# 远程复制(scp)scp local.file user@remote:/path/ # 本地上传到远程scp user@remote:/path/file ./ # 远程下载到本地scp-r dir/ user@remote:/path/ # 复制目录scp-P2222file user@remote:/path/ # 指定端口(大写 P)# 退出exit
shutdown-h now # 立即关机shutdown-h20:25 # 定时关机shutdown-h +10 # 10分钟后关机shutdown-r now # 立即重启shutdown-r +30 '提示信息'# 30分钟后重启并通知用户shutdown-c# 取消关机计划reboot# 强制重启
crontab-e# 编辑计划任务crontab-l# 查看计划任务# 格式:分 时 日 月 周 命令# 示例:00 * * * /data/shell/del-log.sh # 每天0点执行08 * * 1 /data/shell/backup.sh # 每周一8点执行*/30 * * * * /data/shell/check.sh # 每30分钟执行
# systemd(新版本)systemctl start 服务名 # 启动服务systemctl stop 服务名 # 停止服务systemctl restart 服务名 # 重启服务systemctl status 服务名 # 查看服务状态systemctl enable 服务名 # 设置开机启动systemctl disable 服务名 # 取消开机启动# service(旧版本)service 服务名 startservice 服务名 stopservice 服务名 status
yum install package_name # 安装软件包yum remove package_name # 卸载软件包yum update package_name # 更新软件包yum list # 列出已安装的包yum search package_name # 搜索软件包yum clean all # 清理缓存
sudoaptinstall package_name # 安装软件包sudoapt remove package_name # 卸载软件包sudoapt upgrade # 更新已安装的包sudoapt update # 更新软件源apt search package_name # 搜索软件包
wget https://example.com/file.zip # 下载文件
#!/bin/bash # 指定解析器# 这是注释echo"Hello World"
name="John"echo$nameecho"My name is ${name}"# 命令执行结果赋值current_date=$(date)file_count=$(ls|wc-l)
if[ condition ];then# 条件成立时执行elif[ condition ];then# 另一个条件else# 条件不成立时执行fi# 常用条件[-ffile]# 文件是否存在[-ddir]# 目录是否存在["$a"="$b"]# 字符串相等[$a-eq$b]# 数字相等
foriin{1..10};doecho$idoneforfilein *.txt;doecho$filedonewhile[ condition ];do# 循环体done
cat /etc/shells
# 镜像管理docker images # 查看本地镜像docker search mysql # 搜索镜像docker pull mysql:8.0 # 拉取镜像# 容器管理docker run -di--name=容器名 -p 宿主机端口:容器端口 -e 环境变量 镜像名dockerps# 查看运行中的容器dockerps-a# 查看所有容器# 启停容器docker start 容器名docker stop 容器名docker restart 容器名# 删除容器dockerrm 容器名dockerrm-f 容器名 # 强制删除运行中的容器
# 一步编译gcc hello.c -o hello # 编译并生成可执行文件 hello# 分步编译gcc -E hello.c -o hello.i # 1. 预处理(展开宏和头文件)gcc -S hello.i -o hello.s # 2. 编译(生成汇编代码)gcc -c hello.s -o hello.o # 3. 汇编(生成目标文件)gcc hello.o -o hello # 4. 链接(生成可执行文件)
-o file | |
-c | |
-g | |
-O0 / -O1 / -O2 / -O3 | |
-Wall | |
-Werror | |
-std=c11 / -std=c99 | |
-l | -lm(数学库)、-lpthread(线程库) |
-L | |
-I | |
-D | -DDEBUG |
-static | |
-shared |
# 基本编译gcc hello.c -o hello# 多文件编译gcc main.c utils.c -o program# 开启所有警告gcc -Wall-Wextra hello.c -o hello# 调试版本编译gcc -g-O0 hello.c -o hello_debug# 链接数学库gcc math_demo.c -o math_demo -lm# 链接线程库gcc thread_demo.c -o thread_demo -lpthread# 指定头文件路径gcc -I /usr/local/include hello.c -o hello# 指定库文件路径gcc -L /usr/local/lib hello.c -o hello -lmylib# 生成动态库(.so)gcc -shared-fPIC utils.c -o libutils.so# 使用动态库gcc main.c -L. -lutils-o main
# 注释CC = gccCFLAGS = -Wall -gTARGET = programOBJS = main.o utils.o math.o# 目标:依赖$(TARGET):$(OBJS)$(CC)$(OBJS) -o $(TARGET)# 编译规则main.o: main.c utils.h$(CC)$(CFLAGS) -c main.cutils.o: utils.c utils.h$(CC)$(CFLAGS) -c utils.cmath.o: math.c math.h$(CC)$(CFLAGS) -c math.c# 伪目标.PHONY: cleanclean: rm -f $(OBJS)$(TARGET)
CC = gccCFLAGS = -Wall -g -O2SRCS =$(wildcard *.c)OBJS =$(SRCS:.c=.o)TARGET = program$(TARGET):$(OBJS)$(CC)$^ -o $@%.o: %.c$(CC)$(CFLAGS) -c $< -o $@.PHONY: cleanclean: rm -f $(OBJS)$(TARGET)
Makefile 自动变量:
$@ | |
$^ | |
$< | |
$? | |
$* |
make# 执行默认目标make target # 执行指定目标make-j4# 并行编译(4个并发任务)make-f other.mk # 使用指定的 Makefile 文件make clean # 执行 clean 目标make-n# 只显示命令,不实际执行(调试用)
# 必须使用 -g 选项编译以获得调试符号gcc -g hello.c -o hello
gdb hello # 启动 gdb 调试 hello(gdb) quit # 退出 gdb(可简写为 q)
run | r | |
start | ||
break 行号 | b 行号 | |
break 函数名 | b 函数名 | |
break 文件:行号 | b file:line | |
info breakpoints | i b | |
delete 编号 | d 编号 | |
continue | c | |
next | n | |
step | s | |
finish | fin | |
print 变量 | p 变量 | |
print /x 变量 | ||
display 变量 | disp 变量 | |
list | l | |
backtrace | bt | |
frame | f | |
watch 变量 | ||
set var 变量=值 | ||
help 命令 | h 命令 |
gcc -g-O0 debug_demo.c -o debug_demogdb debug_demo(gdb)break main # 在 main 函数设置断点(gdb) run # 运行(gdb) next # 执行下一行(gdb) print i # 查看变量 i 的值(gdb) backtrace # 查看调用栈(gdb)continue# 继续运行(gdb) quit # 退出
# 开启 core dumpulimit-c unlimited# 运行程序(崩溃后生成 core 文件)./buggy_program# 使用 gdb 分析gdb ./buggy_program core(gdb) bt # 查看崩溃时的调用栈
Esc | ||
i / a / o / I / A / O | ||
: | ||
v / V / Ctrl+v |
i | |
I | |
a | |
A | |
o | |
O | |
s | |
S |
上(k)^ 左(h) <-- 光标 --> 右(l) v 下(j)
h / j / k / l # 左、下、上、右移动w # 移动到下一个单词开头b # 移动到上一个单词开头e # 移动到单词末尾0# 移动到行首$ # 移动到行尾^ # 移动到行首第一个非空字符gg # 移动到文件开头G # 移动到文件末尾nG / :n # 移动到第 n 行Ctrl+f # 向下翻一页(Forward)Ctrl+b # 向上翻一页(Backward)Ctrl+d # 向下翻半页(Down)Ctrl+u # 向上翻半页(Up)H / M / L # 移动到屏幕顶部 / 中间 / 底部{ / }# 按段落上下移动% # 跳转到匹配的括号
# 删除(delete)x # 删除光标处字符dw # 删除到单词末尾dd# 删除整行(并复制到剪贴板)d$ / D # 删除到行尾d0 # 删除到行首ndd # 删除 n 行dG # 删除到文件末尾dgg # 删除到文件开头# 复制(yank)yw # 复制一个单词yy # 复制整行nyy # 复制 n 行y$ # 复制到行尾yG # 复制到文件末尾# 粘贴(put)p # 在光标后粘贴P # 在光标前粘贴# 撤销与重做u # 撤销Ctrl+r # 重做# 修改(change)cw # 修改到单词末尾cc # 修改整行C # 修改到行尾r 字符 # 替换光标处字符R # 进入替换模式(持续替换)# 缩进>># 当前行增加缩进<<# 当前行减少缩进>G # 当前行到末尾增加缩进ngg=G # 自动格式化从第 n 行到末尾# 其他.# 重复上一次操作J # 将下一行合并到当前行~ # 切换大小写
# 查找(普通模式)/pattern # 向下搜索?pattern # 向上搜索n # 跳转到下一个匹配N # 跳转到上一个匹配* # 搜索光标所在单词(向前)# # 搜索光标所在单词(向后)# 查找替换(命令模式):s/old/new # 替换当前行第一个匹配:s/old/new/g # 替换当前行所有匹配:%s/old/new/g # 替换整个文件所有匹配:%s/old/new/gc # 替换整个文件,每次确认:n,ms/old/new/g # 替换第 n 行到第 m 行的所有匹配:%s/old/new/g # 全文替换# 忽略大小写:%s/old/new/gi
v# 字符可视模式(按字符选择)V # 行可视模式(按行选择)Ctrl+v # 块可视模式(矩形选择)# 选中后可执行的操作d / x # 删除选中内容y # 复制选中内容> / <# 缩进/反缩进r 字符 # 替换选中内容为指定字符
# 命令模式:w # 保存:w filename # 另存为:q # 退出:q!# 不保存强制退出:wq / :x / ZZ # 保存并退出:wq!# 强制保存退出(root 权限):r filename # 在光标处插入另一个文件内容:e filename # 打开另一个文件:e!# 重新加载当前文件(放弃修改):bn / :bp # 切换到下一个/上一个缓冲区# 多窗口:sp filename # 水平分屏打开文件:vsp filename # 垂直分屏打开文件Ctrl+w w # 切换窗口Ctrl+w q # 关闭窗口Ctrl+w =# 等分窗口大小Ctrl+w + / Ctrl+w - # 增加/减少窗口高度
# 显示行号:set nu # 显示行号:set nonu # 隐藏行号# 语法高亮:syntax on:syntax off# 搜索高亮:set hlsearch # 高亮搜索结果:set nohlsearch # 取消高亮:nohl # 临时取消本次搜索的高亮# 缩进设置:set tabstop=4# Tab 宽度:set shiftwidth=4# 自动缩进宽度:set expandtab # Tab 转为空格:set autoindent # 自动缩进# 在当前会话查看设置:set # 查看已修改的设置:set all # 查看所有设置# 永久配置(写入 ~/.vimrc)echo"set nu">> ~/.vimrcecho"set tabstop=4">> ~/.vimrcecho"syntax on">> ~/.vimrc
# 批量注释(块模式)Ctrl+v → 选择多行 → I → 输入 # 或 // → Esc# 批量取消注释Ctrl+v → 选择注释符号 → d# 大小写转换gUw # 光标处单词转大写guw # 光标处单词转小写gUU # 当前行全转大写guu # 当前行全转小写# 数字递增 / 递减Ctrl+a # 光标处数字 +1Ctrl+x # 光标处数字 -1# 执行 Shell 命令:!command # 执行外部命令:r !command # 将命令输出插入当前文件