有时,我必须指定完整路径,因为似乎没有参考 $PATH:
#### I have `virtualenv` and it's on my path ####
$ virtualenv --version # `virtualenv` is on my path
1.7.1.2
$ which virtualenv # further details
/usr/bin/virtualenv
$ echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games
#### However, I can't `stat virtualenv`: ####
$ stat virtualenv
stat: cannot stat `virtualenv': No such file or directory
#### I have to use `stat `which $BINARY`` ####
$ stat `which virtualenv`
File: `/usr/bin/virtualenv'
Size: 54 Blocks: 8 IO Block: 4096 regular file
Device: ca01h/51713d Inode: 22860 Links: 1
Access: (0755/-rwxr-xr-x) Uid: ( 0/ root) Gid: ( 0/ root)
Access: 2012-11-28 23:48:03.919400541 -0500
Modify: 2012-04-23 06:34:09.000000000 -0400
Change: 2012-11-28 17:24:31.335400569 -0500
Birth: -
$
which virtualenv
如果它在我的路上,为什么我必须使用它?
答案1
$PATH
仅在以下情况下才会被咨询执行命令。当 shell 必须搜索要执行的命令时,它会查阅$PATH
并遍历目录列表,$PATH
挑选第一个与提供的名称匹配的可执行文件(在权限中设置了适当的执行位),然后执行它。
当你运行 时stat virtualenv
,你将把它virtualenv
作为参数传递给stat
程序。假设 是stat
用 C 编写的,那么它将virtualenv
在程序的主方法中被视为一个参数:
int main(int argc, char** argv)
包含argv
两个元素:索引 0 是用于调用程序本身的命令,因此它是“stat”。索引 1 是第一个命令行参数,因此它是“virtualenv”。
发生这种情况的原因是,exec()
当您用子进程替换当前进程时,一系列系统调用(如果您感兴趣,请查阅手册页)允许您传递一个命令行参数数组。shell 会调用一些变体,exec()
并解析您的命令行以确定要作为哪个命令行参数数组传递argv
。
由于stat
不知道您提供的文件是普通文件、符号链接、硬链接、可执行文件还是目录等,因此它不会搜索$PATH
以找到它。它将传入的参数视为指定在程序被调用时展开到当前工作目录的${PWD}/virtualenv
位置。这称为${PWD}
stat
相对路径。
几乎所有接受文件名相对路径作为参数的命令都会不是search $PATH
,尽管一些命令可能会这样做,例如bash
或者如果您告诉它们在子 shell 环境中执行命令。没有什么可以阻止任何任意命令通过任何特定的环境变量来查找您提供的文件,但这是特定于应用程序的行为。搜索相对路径ssh
根本没有任何意义,因为仅适用于可执行文件。$PATH
$PATH
答案2
PATH
当您尝试执行某件事时,需要并咨询。
与 Windows 不同,在 Unix 上,您始终需要使用路径指定可执行文件。./foo.bin
或/usr/bin/foo.bin
。但为了简单起见,存在一个称为的东西PATH
。因此,只需输入foo.bin
因为/usr/bin
恰好在您的路径中即可。
如果你想知道哪个文件是通过 解析的foo.bin
,which
有告诉你:/usr/bin/foo.bin
。
因此,所有其他接受可执行文件和不可执行文件作为参数的 UNIX 工具可能都不会查阅PATH
。
答案3
在执行程序时,shell 会参考 PATH 来查找要执行的程序。当它是一个参数(例如示例中的which
或stat
命令)时,shell 会将其传递给它找到的程序,然后程序决定如何处理它。
该which
命令内置于 bash 中,它接受参数并查阅 shell 的路径来确定 shell 将如何执行该命令。大多数其他程序(包括大多数内置于 bash 中的其他程序)(例如stat
您的示例中的程序)仅使用该路径并尝试在文件系统的当前目录中找到它。
因此,执行命令(以及which
试图找出要执行什么命令之类的操作)是唯一使用 PATH 的操作。