什么时候在 shell 使用中咨询 $PATH ?

Dmi*_*sky 1 linux bash command-line

有时,我必须指定完整路径,因为 $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: -
$ 
Run Code Online (Sandbox Code Playgroud)

which virtualenv如果它在我的路径上,为什么我必须使用它?

all*_*tic 5

$PATH仅在执行命令时查询。当 shell 必须搜索要执行的命令时,它会查询$PATH并遍历其中的目录列表,$PATH并选择与提供的名称匹配的第一个可执行文件(在权限中设置了适当的执行位),然后执行它。

当您运行时stat virtualenv,您将virtualenv作为参数传递给stat程序。假设它stat是用 C 编写的,那么它就会将其virtualenv视为程序 main 方法中的一个参数:

int main(int argc, char** argv)

argv包含两个元素:索引0是你用来调用程序本身的命令,所以它的“统计”。索引 1 是第一个命令行参数,所以它是“virtualenv”。

发生这种情况是因为exec()当您用子进程替换当前进程时,系统调用系列(如果您好奇,请查看联机帮助页)允许您传递命令行参数数组。shell 确实调用了 的某些变体,exec()它会解析您的命令行以确定要作为 传递的命令行参数数组argv

由于stat不知道您提供的文件是否是普通文件、符号链接、硬链接、可执行文件与否、目录等,因此它不会搜索$PATH以找到它。它将传入的参数视为指定,具体而言,${PWD}/virtualenv在调用程序${PWD}时扩展到当前工作目录的位置stat。这称为相对路径

几乎所有接受文件名的相对路径作为参数的命令都不会search $PATH,尽管有一些命令可能会这样做,例如bash或者ssh如果您告诉它们在子 shell 环境中执行命令。没有什么可以阻止任何任意命令查看您提供的文件的任何特定环境变量,但它是特定于应用程序的行为。搜索$PATH相对路径根本没有任何意义,因为$PATH仅用于可执行文件。