如果我想创建一个像git -v ……类似的命令,其实很简单。制作一个可执行文件,放在系统PATH路径下,在终端输入名字就能运行。
那么具体怎么制作呢?
一、什么是命令?命令可以干什么。
命令,简单说就是你告诉电脑"帮我做某件事"的一句话。
在计算机世界里,命令通常指的是你在命令行终端(也叫Shell)里敲的那些英文单词。比如:
bash
ls # 列出当前文件夹下有什么文件
cd Desktop # 进入"桌面"文件夹
ping baidu.com # 测试能不能连上百度
命令能干什么?
命令能干的事太多了,几乎涵盖了你用电脑能做的所有操作,只不过是用文字而不是鼠标点击来完成。
比如:
-
查看文件:ls(Linux/Mac)或 dir(Windows)
-
创建文件夹:mkdir 照片
-
删除文件:rm 旧文件.txt
-
复制文件:cp 源文件 目标文件
-
移动/重命名:mv 旧名 新名
二、可执行文件是什么?怎么制作可执行文件?
可执行文件,简单说就是电脑能直接"读懂"并"执行"的文件。
我们人类写的代码是英文单词(比如 int main()),电脑的CPU只认识机器指令(一堆0和1)。可执行文件就是把人类写的代码翻译成CPU能识别的机器指令后,打包成一个文件。
在C语言里,我们所写的代码都是以.c结尾的文件,变成可执行文件需要四个步骤:
例如:
你写的代码 → 预处理 → 编译 → 汇编 → 链接 → 可执行文件
hello.c → hello.i → hello.s → hello.o → hello.exe (Windows)
→ hello (Linux/Mac)
可执行文件的"样子"
在不同操作系统上,可执行文件的"长相"不一样:
| Windows | PE(Portable Executable) | .exe、.dll | notepad.exe |
| Linux | ELF(Executable and Linkable Format) | 无固定后缀 | ls、gcc |
| macOS | Mach-O | 无固定后缀 | ls、gcc |
三、关于环境变量(PATH)
一、什么是环境变量(PATH)
环境变量是操作系统里的一组全局设置,其中有一个叫 PATH 的变量,它的作用是:
告诉系统:“当用户在命令行敲了一个名字时,应该去哪些文件夹里找对应的 .exe 文件。”
PATH 里存的是一堆文件夹路径,用分号隔开。比如:
text
C:\\Windows\\System32;
C:\\Program Files\\Git\\bin;
C:\\Users\\你的用户名\\AppData\\Local\\Programs\\Python\\Python312;
当你在命令行敲 git 时,系统会按顺序去这些文件夹里找 git.exe,找到就运行。
二、怎么在环境变量里声明
方法一:临时添加(只对当前命令行窗口有效)
cmd
set PATH=%PATH%;D:\\myproject
mycmd
方法二:永久添加(推荐)
右键 此电脑 → 属性
点击 高级系统设置
点击 环境变量
在 系统变量 或 用户变量 里找到 Path,双击
点击 新建,输入你的程序所在文件夹路径(比如 D:\\myproject)
点 确定 保存
重新打开命令行窗口,输入 mycmd 就能用了
看到这然后你会不会有几个小疑惑,环境变量存入的都是地址,命令为什么是一个名字?为什么把可执行文件地址添加到环境变量就可以输入命令名不会再报错了?
核心答案:环境变量 PATH 就是操作系统的"地图"
你在终端敲 mycmd 并回车时,操作系统(Shell)其实在做一件很简单的事:
"用户让我执行 mycmd,但我不知道 mycmd 这个文件在硬盘的哪个角落,我得去查一下地图。"
这个"地图"就是环境变量 PATH。
而命令名字就是 .exe 文件的文件名(不含扩展名)。
四、我写的命令也能支持 -v、-e 这种参数吗?
当然能!由你代码里怎么处理 argv 决定。
你写的 C 程序,main 函数长这样:
c
int main(int argc, char *argv[])
-
argc:参数个数
-
argv[]:参数列表,argv[0] 是命令名,argv[1] 是第一个参数
-v、-e、–help、–version,这些本质上就是传给程序的普通字符串,你完全可以在代码里自己解析。
一个最简单的支持 -v 的例子:
c
#include <stdio.h>
#include <string.h>
int main(int argc, char *argv[]) {
// 检查有没有 -v 参数
for (int i = 0; i < argc; i++) {
if (strcmp(argv[i], "-v") == 0) {
printf("版本 1.0.0\\n");
return 0;
}
if (strcmp(argv[i], "-e") == 0) {
printf("执行扩展功能\\n");
return 0;
}
if (strcmp(argv[i], "–help") == 0) {
printf("用法: mycmd [-v] [-e] [–help]\\n");
return 0;
}
}
printf("普通模式,没有特殊参数\\n");
return 0;
}
编译运行:
bash
mycmd # 输出: 普通模式,没有特殊参数
mycmd -v # 输出: 版本 1.0.0
mycmd -e # 输出: 执行扩展功能
mycmd –help # 输出: 用法: mycmd [-v] [-e] [–help]
所以 -v、-e 这些不是系统给的魔法,是你自己代码里写的逻辑。
为什么 Git 的 -v 能输出版本,你的也能?
因为 Git 的开发者在 git.exe 的代码里写了类似上面这样的逻辑。所有命令的参数行为,都是开发者自己定义的。
-
git -v 输出版本 → 是 Git 开发者写的
-
python -v 输出版本 → 是 Python 开发者写的
-
mycmd -v 输出什么 → 是你自己写的
到这你已经完全会自己做命令了,当我信心满敲下第一个属于自己的命令行时,操作系统在干什么。
第1步:你想叫醒它(在命令行执行)
你打开 CMD(命令行),敲了:
cmd
mycmd
这时候,操作系统(Windows)被惊动了,它接下了你的请求。
第2步:操作系统开始"翻箱倒柜"(查找 PATH)
操作系统拿到 hello 这个名字后,脑子里想的是:"我上哪去找这个叫mycmd 的机器人?"
它手里有一张地图,这张地图就是 PATH 环境变量。
地图上画着很多文件夹:
text
– C:\\Windows
– C:\\Program Files
– D:\\mycode ← 咦,你正好在这个列表里!
– …
操作系统按顺序翻:
去 C:\\Windows 找 hello.exe?没有。
去 C:\\Program Files 找?没有。
去 D:\\mycode 找?找到了!
如果 D:\\mycode 不在 PATH 地图上,操作系统就会说:"找不到",这就是你之前报错的原因。
第3步:操作系统把"命令名"和"参数"一起塞给你(启动程序)
找到了 mycmd.exe,操作系统就把它从硬盘加载到内存里,然后把你在命令行敲的一整句话原封不动地传给程序的入口 main 函数:
-
你敲的是 mycmd -v -e
-
操作系统传给 main 的就是:argc=3,argv[0]="hello",argv[1]="-v",argv[2]="-e"
第4步:你的代码决定怎么做(解析参数)
现在轮到你的代码执行了。如果你的代码里有:
c
if (argv[1] == "-v") { 打印版本号; }
那它就会输出版本号。如果代码里没写,那 -v 就会被忽略或报错。




