Linux 支线学习资料
文件操作三剑客:cp、mv、rm,以及编译器参数 -c 与 -o
一、为什么学这组命令?
之前你已经学会在命令行里"看"(ls)、"走"(cd)、"建"(mkdir)、"编译运行"(gcc ./a.out)。现在要继续往你的"命令武器库"里添加三个极其常用的文件操作工具 :复制、移动/重命名、删除。同时,我们还要深入 gcc 的两个选项,让你理解编译的内部阶段。
二、文件操作命令精讲
1. cp ------ 复制文件或目录
它干什么?
cp 是 copy 的缩写,用于复制文件或整个目录,产生一个副本。
基本用法
bash
cp 源文件 目标路径
源文件是你要复制的那个东西,目标路径可以是一个新文件名,也可以是一个目录(就把文件原样复制进去)。
常用选项
-r(recursive):递归复制,用于复制整个目录时必须加,否则会报错。-i(interactive):如果目标文件已存在,会询问你是否覆盖,防止误覆盖。-v(verbose):显示详细的复制过程,让你知道它在干什么。
实例演示
bash
$ cp hello.c hello_backup.c # 将 hello.c 复制一份,命名为 hello_backup.c
$ cp hello.c project/ # 将 hello.c 复制到 project 目录下(文件名不变)
$ cp -r my_folder new_folder # 复制整个 my_folder 目录及其内部所有内容到 new_folder
$ cp -i a.txt b.txt # 如果 b.txt 已存在,会提示是否覆盖
易错提醒
- 复制目录时必须加
-r,否则cp: -r not specified; omitting directory。 - 如果目标是一个已存在的目录,文件会被复制到目录里面 ,而不是把目录替换掉。举个例子:
cp file dir会把file放进dir里,变成dir/file。如果你想把目录本身替换掉,需要用cp -r source_dir target_dir并且target_dir要么不存在,要么就要合并内容。
2. mv ------ 移动文件或重命名
它干什么?
mv 是 move 的缩写,有两个作用:
- 移动文件或目录到另一个位置;
- 重命名文件或目录(其实移动到一个不存在的名字就是重命名)。
基本用法
bash
mv 源 目标
- 如果目标是一个已存在的目录,源会被移动到这个目录里面。
- 如果目标是一个不存在的名字,源就会被重命名为目标。
常用选项
-i:覆盖前询问。-v:显示移动过程。
实例演示
bash
$ mv hello.c src/ # 把 hello.c 移动到 src 目录下(src 必须存在)
$ mv a.out hello # 将 a.out 重命名为 hello(相当于改名)
$ mv old_name.txt new_name.txt # 重命名文件
$ mv dir1 dir2 # 如果 dir2 不存在,则重命名;若存在,则把 dir1 移入 dir2 内
易错提醒
mv移动或重命名时,如果目标文件已存在,会直接覆盖 (不加-i时不警告),所以使用时要小心。建议养成加-i的习惯,或者在重要操作前先ls看看有没有重名。
3. rm ------ 删除文件或目录
⚠️ 这个命令极其危险,删除后无法恢复,一定要谨慎!
它干什么?
rm 是 remove 的缩写,用来删除文件或目录。
基本用法
bash
rm 文件
rm 目录...(需要选项)
必须掌握的选项
-i:删除前逐一询问确认(安全)。-r:递归删除目录及其所有内容(删除目录必须加这个)。-f:强制删除,不问确认,就算文件不存在也不报错(危险,慎用)。-rf:强制递归删除(极其危险 ,不要轻易使用,尤其不要带*或/)。
实例演示
bash
$ rm old_file.txt # 删除一个文件
$ rm -i test.c # 删除前会问 "rm: remove regular file 'test.c'?" 回答 y 才删
$ rm -r old_project # 删除整个 old_project 目录及其所有子文件/子目录
$ rm -rf dangerous_dir # 强制删除目录,不问任何话(危险!)
黄金法则
- 删除前先用
ls确认要删的东西。 - 尽量使用
-i给自己一次反悔的机会。 - 永远不要执行
sudo rm -rf /(会删掉整个系统!)。 - 如果只是想清空一个目录,可以用
rm -r 目录/*,但也要再三确认路径。
三、深入 gcc 的参数 -c 与 -o
之前我们用 gcc hello.c 会直接生成可执行文件,但其实编译过程分四步:预处理 → 编译 → 汇编 → 链接。
-c 和 -o 就是控制这些阶段的利器。
man gcc 里的官方解释(已经帮你翻译成人话)
-
-c:Compile or assemble the source files, but do not link.意思是:编译或汇编源文件,但不进行链接 。
通俗讲:只把
.c变成.o(目标文件),不生成最终可执行程序。 -
-o file:Place output in file file. This applies to whatever sort of output is being produced.意思是:把输出放到指定文件,无论输出的是什么类型的文件(可执行文件、目标文件、汇编文件等)。
gcc -c 详解:只编译不链接
当你的项目有多个源文件时(例如 main.c 和 func.c),你不能一次性直接生成可执行程序,因为每个 .c 文件需要先单独编译成 .o 目标文件,最后再把这些 .o 文件链接成一个完整的程序。
工作流程:
bash
gcc -c main.c # 生成 main.o,里面是机器码但还不完整
gcc -c func.c # 生成 func.o
gcc main.o func.o -o myprogram # 链接两个 .o 文件,生成可执行文件 myprogram
./myprogram
关键理解:
.o文件是二进制代码,但不能直接执行,因为它缺少启动代码和其他函数的地址链接。- 不加
-c的gcc会自动帮你做完编译和链接两步,一键生成最终程序。但大型项目必须分步编译,因为修改一个文件时只需重新编译那个文件即可。
gcc -o 详解:自定义输出文件名
-o 可以搭配任何阶段的输出来改名。
示例:
bash
gcc hello.c -o hello # 可执行文件命名为 hello
gcc -c hello.c -o hi.o # 目标文件命名为 hi.o(而不是默认的 hello.o)
gcc hi.o -o hello # 把 hi.o 链接成 hello
如果不加 -o,默认输出名称是:
- 只编译时:
源文件名.o - 直接链接时:
a.out
四、✅ 已掌握命令清单(更新版)
以下清单包含之前掌握的核心五命令,加上今天新掌握的三个文件操作命令和两个编译器参数。
| 命令 / 参数 | 用途 | 关键写法或选项 | 备注 |
|---|---|---|---|
ls |
列出目录内容 | ls -l, ls -a |
大小写敏感 |
cd |
切换目录 | cd .., cd ~, cd - |
回家的多种姿势 |
mkdir |
创建目录 | mkdir -p a/b/c |
父目录自动创建 |
gcc |
编译C程序 | gcc file.c -o name |
默认生成 a.out |
./程序名 |
运行当前目录程序 | ./a.out |
必须加 ./ |
cp |
复制文件/目录 | cp -r 源目录 目标, cp -i |
复制目录必须 -r |
mv |
移动/重命名 | mv 源 目标, mv -i |
小心覆盖已有文件 |
rm |
删除文件/目录 | rm -r 目录, rm -i |
极其危险,操作前确认 |
gcc -c |
只编译不链接 | gcc -c file.c |
生成 .o 目标文件 |
gcc -o |
自定义输出名 | gcc -o 输出名 |
适用于任何阶段 |
五、综合练习(边学边练,形成肌肉记忆)
请在终端中一步步完成以下任务,不要跳步,每步都观察 ls 输出。
-
在家目录下创建文件夹
file_practice并进入。 -
创建三个文件:
a.txt、b.txt、c.txt(用touch命令快速创建空文件,如touch a.txt。如果没有touch,就用nano a.txt随便写点东西保存)。 -
将
a.txt复制为a_backup.txt。 -
将
b.txt重命名为b_new.txt(用mv)。 -
创建一个子目录
subdir,把c.txt移入其中。 -
复制整个
subdir目录及其内容到subdir_copy(注意用-r)。 -
删除
a_backup.txt文件(建议加-i体验确认过程)。 -
删除
subdir_copy整个目录(用rm -r,不加-f先确认)。 -
在
file_practice目录下创建一个calc.c,内容如下:cint add(int a, int b) { return a + b; }这是一个没有 main 函数的源文件,单独不能生成可执行程序。
-
用
gcc -c calc.c -o calc.o生成目标文件,并观察ls -l calc.o。 -
再创建一个
main.c,内容如下:c#include <stdio.h> int add(int, int); int main() { printf("10 + 20 = %d\n", add(10,20)); return 0; } -
用
gcc -c main.c生成main.o。 -
用
gcc main.o calc.o -o calculator链接生成可执行文件。 -
运行
./calculator,检查输出。 -
最后,用
cd ..回到家目录,并删除整个file_practice目录 (rm -r file_practice,要求输入y确认)。
六、答案与关键点解析
mkdir file_practice && cd file_practicetouch a.txt b.txt c.txt(若没有 touch,可用nano a.txt保存空文件)cp a.txt a_backup.txtmv b.txt b_new.txtmkdir subdir && mv c.txt subdir/cp -r subdir subdir_copy(一定要加-r)rm -i a_backup.txt(提示时按y)rm -r subdir_copy(提示时会问是否进入目录、是否删除文件,按y确认)- 创建
calc.c,只含add函数,无main。 gcc -c calc.c -o calc.o,ls -l可见calc.o,权限为-rw-r--r--(没有执行权限)。- 创建
main.c,包含头文件、声明和main。 gcc -c main.c,生成main.o。gcc main.o calc.o -o calculator,两个.o链接成一个可执行文件calculator。./calculator输出10 + 20 = 30。cd ..,然后rm -r file_practice,遇到提示按y确认。
关键理解:
- 第9-14步刻意让你体验了 "分离编译" :
calc.o和main.o单独生成,最后链接。这就是gcc -c的典型使用场景。 rm -r删除目录时必须加-r,系统会询问你是否进入目录、是否删除文件,这是安全机制;如果加了-f则不会问。
七、学习检查清单
- 复制一个目录到另一个地方,命令怎么写?最容易忘记的选项是什么?
mv file1 file2,如果file2已经存在会怎样?如何让它询问你是否覆盖?- 删除一个非空目录
data,必须用哪个选项?为什么建议先加-i? gcc -c hello.c生成了什么文件?能直接运行吗?- 如何把编译出的目标文件命名为
myobj.o? - 简述从多个
.c文件到一个可执行程序的完整编译链接步骤。
如果这些问题你都能流畅回答出来,恭喜你,这一支线的所有内容已经被你内化。接下来可以在真实项目里多用 cp、mv、rm 管理文件,用 gcc -c 体验多文件编译,命令行能力会越来越强。继续加油!