cd ./命令在Bash中的运行方式究竟如何?

时间:2016-01-25 17:05:17

标签: linux bash unix scripting cd

我很好奇,当我在bash中使用cd命令时,命令

cd foobar

cd ./foobar

以同样的方式工作。我明白,./是指当前的目录目录,但为什么“cd foobar”有效呢?它只是默认的,当我不在开头编写./时,程序会自己添加它,还是更复杂?

2 个答案:

答案 0 :(得分:9)

bash中的cd命令(有点间接地,如下所述)调用chdir()系统调用,behavior of which is specified by POSIXcd 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 somewherecd ./somewhere将您置于不同的目录中。没有前导/且没有前导...组件的目录名称(其中cd .hidden不计算 - 主要组件是.hidden - 但是使用cd ./visible搜索cd ../visibleCDPATH做计数)。

例如,考虑这个树结构(仅显示目录):

.                - current directory
./somewhere
./src
./src/somewhere

假设您有CDPATH=src:。然后cd somewhere将转到./src/somewherecd ./somewhere将(不出所料)转到./somewhere。如果键入cd src/somewhere等名称,cd命令将依次为/xyz/pqr/src/somewhere上的每个目录/xyz/pqr搜索子目录CDPATH。我永远使用CDPATH(在我自己的机器上有7个目录;在我的工作机器上有14个目录)。

  • 经验法则:使用CDPATH=:…whatever…

这会将当前目录放在搜索路径上,并且通常是最理智的行为。

类似的故事适用于搜索普通的外部(非别名,非功能,非内置)命令。以斜杠开头的命令名称是绝对路径名;包含斜杠的命令名称相对于当前目录;在$PATH上搜索没有斜杠的命令名称。