我很好奇,当我在bash中使用cd
命令时,命令
cd foobar
和
cd ./foobar
以同样的方式工作。我明白,./是指当前的目录目录,但为什么“cd foobar
”有效呢?它只是默认的,当我不在开头编写./
时,程序会自己添加它,还是更复杂?
答案 0 :(得分:9)
bash中的cd
命令(有点间接地,如下所述)调用chdir()
系统调用,behavior of which is specified by POSIX。 cd
shell命令本身also has a POSIX specification for its behavior,可能比适用于可访问/可读定义的更详细。
是的,所有操作(不仅是chdir()
,还有fopen()
和其他操作)的默认值是当前的工作目录。
这不是针对bash的,而是操作系统级行为:"当前工作目录"是内核跟踪的每个进程的元数据的一部分,并影响对内核的文件系统级请求:任何语言的任何程序都可以调用chdir("foo")
或open("foo", O_RDONLY)
,行为将是在当前目录中查找foo
,从父进程继承或使用之前的chdir()
调用进行修改。
也就是说,出于bash的目的,cd ./foo
更具体而不仅仅是cd foo
:前者表示你显式想要foo
子目录当前的工作目录。在bash中,如果设置了CDPATH
shell变量,那么cd foo
将查看其中列出的所有目录,而cd ./foo
显式只询问当前工作目录下的foo
尝试此实验:
# setup
tempdir=$(mkdir -d "${TMPDIR:-/tmp}/cdpath-test.XXXXXX")
mkdir -p "$tmpdir/i-am-a-test-directory"
CDPATH=".:$tempdir"
# this works, because CDPATH is honored
cd /
cd i-am-a-test-directory
# this does not, because you're explicitly asking for a directory that does not exist
cd /
cd ./i-am-a-test-directory
# cleanup
rm -rf "$tempdir"
unset CDPATH
答案 1 :(得分:2)
暂时忽略CDPATH
环境变量,cd
之后的名称是目录路径名。 Unix中只有两种路径名:
/
/
内核将所有相对名称视为相对于当前目录 - 就好像名称前缀为./
一样。
如果设置了CDPATH
,则会使搜索变得复杂,然后可以想到cd somewhere
和cd ./somewhere
将您置于不同的目录中。没有前导/
且没有前导.
或..
组件的目录名称(其中cd .hidden
不计算 - 主要组件是.hidden
- 但是使用cd ./visible
搜索cd ../visible
或CDPATH
做计数)。
例如,考虑这个树结构(仅显示目录):
. - current directory
./somewhere
./src
./src/somewhere
假设您有CDPATH=src:
。然后cd somewhere
将转到./src/somewhere
,cd ./somewhere
将(不出所料)转到./somewhere
。如果键入cd src/somewhere
等名称,cd
命令将依次为/xyz/pqr/src/somewhere
上的每个目录/xyz/pqr
搜索子目录CDPATH
。我永远使用CDPATH
(在我自己的机器上有7个目录;在我的工作机器上有14个目录)。
CDPATH=:…whatever…
这会将当前目录放在搜索路径上,并且通常是最理智的行为。
类似的故事适用于搜索普通的外部(非别名,非功能,非内置)命令。以斜杠开头的命令名称是绝对路径名;包含斜杠的命令名称相对于当前目录;在$PATH
上搜索没有斜杠的命令名称。