命令行(command not found)

初学者在接触命令行的时候,肯定会经常碰到command not found这样的提示,有些时候可能会因此困惑,我明明是有这个文件的,但是为什么找不到命令呢

windows or *nix

windows下的命令行用起来的感觉差强人意,如果使用命令行还是使用*nix(linux,unix)比较好,这里默认使用linux的bash来进行解释

shell运行命令的方式

bash中,有四种命令可以在终端执行,分别是函数和别名,内建命令,外部命令,以及可执行文件

在windows下的可执行文件是以.exe .bat .sh后缀名结尾的文件,但是在linux下任何文件只要有x可执行权限都可以执行 (x可执行权限表现为使用ls -al命令中出现为最前面的十个字符,分别表示文件类型 拥有者权限 用户组全选 其他用户权限)

函数和别名

在终端下可以通过在shell的配置文件中编写函数来作为命令使用,比如在homestead虚拟机中有一个函数artisan,使用type artisan可以看到artisan的代码

默认的shell文件是/etc/profile 和.profile,而bash的默认配置文件则是/etc/bash.bashrc和.brshrc,其中etc目录下的是全局配置文件, .号开头的是用户专属配置文件

artisan()
{
php artisan "$@"
}

当使用artisan命令的时候,shell会调用php去执行当前目录下的artisan文件,并把所有的参数一起传递过去,通过这个函数,就可以让我们不用每次都输入php artisan "arguments"来工作了

还有一种是别名,比如ll命令,通过内建命令alias命令可以创建别名,比如使用type ll的时候,就可以很清晰的看到
ll is aliased to `ls -alF'

内建命令

内建命令其实就是shell本身中已经编写好的指令,这些指令通常是不能用which查看到的,比如cd history命令等,在命令行使用type 命令可以看到一个命令是什么类型的命令,比如使用

type  history

就能看到输出 history 是shell 内建

history 显示当前用户使用过的所有的命令记录

外部命令

那么接下来外部命令是什么?
在解释外部命令之前,先引入一个词汇环境变量,你应该或多或少的听过它的另一个命令PATH,在终端下输入下列命令就可以看到当前所有的环境变量了, 其实它就是很多路径组成的集合

echo $PATH

如果是windows下 则是echo %PATH%

因为当从终端输入字符之后,shell会执行下面三个步骤
- 判断命令是不是函数或者别名(函数和别名拥有执行的最高优先级)
- 判断命令是不是内建命令
- 在环境变量的所有路径下寻找与命令匹配的文件

如果这些过程都没有找到可执行文件,那么就会返回command not found 或者未找到 xx 命令这样的错误信息了

如果在执行命令的时候,直接指定了完整路径的话,那么shell将不会执行这三个步骤,从而定位到该文件来执行该命令

可执行文件

在linux中,默认的所有的可执行程序都必须有路径才可以执行,其实外部命令也是一个可执行文件,这里为了区分外部命令,定义为带有路径执行的可执行文件,如./a.out 就是一个非常常见的一个可执行文件

a.out 是gcc不加任何参数编译输出的默认的文件

这里我想要表达的是,linux下任何一个文件,给出完整路径后,可以在任何目录下执行,而不依赖于环境变量
比如ls 命令,直接使用ls -al可以列出当前目录下的所有文件,而它所在的路径一般是/bin/ls
所以在终端下输入

/bin/ls -al

ls -al是完全一样的

尾语

当你一个命令不是函数,别名,内建命令,也不是外部命令,也没有给出完整路径 仍然都找不到命令的话,那么就只有两种原因
- 你的计算机里没有安装这个程序
- 你的命令输入错了
最后让command not found都见鬼去吧