在《学习UNIX操作系统》一书中,有一节“3.1.8 列出文件”描述了该ls
命令。
在段落中ls -l
描述了该命令输出的列。
该命令的第二列ls -l
包含一个数字。该数字在书中被描述为“链接到此文件和目录的数量”。(链接到与相关数字同一行的最后一列中命名的文件或目录。)
我尝试了这个命令,并将输出与当前目录中文件和目录的实际数量进行了比较。
ls -l
drwxr-xr-x 6 azbc staff 192 Sep 7 16:09 test
在目录中test
,我有 2 个子目录和 1 个文件,以及 1 个隐藏文件和当前目录的列表,再加上父目录的列表,因此共有 6 个文件和目录。
ls -a -F
./ .hidden_file.txt dir_2/
../ dir_1/ file_1.sh
我觉得将所有文件和目录(包括隐藏文件和目录)标识为链接到当前目录是合乎逻辑的。将父目录标识为链接到当前目录也是合乎逻辑的。
但是为什么当前目录被标识为与自身链接?
测试目录的命令ls -la
给出以下输出。(/
如果是目录,则 -F 选项在目录名后面显示 ,如果是可执行文件,则显示 *)
ls -la -F
total 0
drwxr-xr-x 6 azbc staff 192 Sep 7 16:09 ./
drwxr-xr-x+ ?? azbc staff ?? Sep 7 16:06 ../
-rw-r--r-- 1 azbc staff 0 Sep 7 16:09 .hidden_file.txt
drwxr-xr-x 2 azbc staff 64 Sep 7 16:06 dir_1/
drwxr-xr-x 2 azbc staff 64 Sep 7 16:06 dir_2/
-rwx--x--x 1 azbc staff 0 Sep 7 16:06 file_1.sh*
文件本身仅用一个链接标识。文件是否链接到自身?还是链接到其所在的目录?
由于目录列表中目录本身在列表中表示,因此在逻辑上可以算作链接。
然而,在文件本身的列表中,只有文件本身出现在列表中。
ls -la -F file_1.sh
-rwx--x--x 1 azbc staff 0 Sep 7 16:06 file_1.sh
由此可以合理地说该文件与其自身相链接。
然而,对我来说,说文件链接到它所在的目录似乎更合乎逻辑。
这似乎不是结果。
或者,链接文件的列表仅仅是对命令列表输出中存在的文件和目录的计数,而不是对文件系统中文件或目录的真实链接的识别?
编辑:作为回复@George Udosen, 在:
“现在尝试回答您在评论中提出的问题:
“这里列出的链接是什么?列出的是文件本身吗?还是列出的是包含该文件的目录?”
如果我列出目录test
:
ls -la -F test
...
drwxr-xr-x 2 azbc staff 64 Sep 7 16:06 dir_1/
...
-rwx--x--x 1 azbc staff 0 Sep 7 16:06 file_1.sh*
dir_1
它通过链接来标识目录2
!
如果我列出该目录test/dir_1
ls -la -F test/dir_1
total 0
drwxr-xr-x 2 azbc staff 64 Sep 7 16:06 ./
drwxr-xr-x 9 azbc staff 288 Sep 7 21:37 ../
嘿,确实如此!!它列出了2
条目!
该文件file_1.sh*
已通过链接识别1
。如果我列出文件file_1.sh
ls -la -F test/file_1.sh
-rwx--x--x 1 azbc staff 0 Sep 7 16:06 test/file_1.sh*
嗬!!它确实列出了1
条目!!,也就是file_1.sh
它自己!并再次用条目标识该文件1
。
顺便问一下,我能得出结论吗?列出的每个带有1
链接的条目都是文件而不是目录?然而,情况似乎并非如此,因为符号链接也被列为具有1
链接/1
条目。
答案1
我建议你读如果 Linux 上的所有内容都是文件,那么目录是什么?了解有关目录结构、历史和目录工作原理及其元素(inode、结构等)的术语的更深入的知识dirent
,尽管这不是这个问题所必需的。
什么是点“。”和点点“..”目录?
看着format of directories
1971 年的手册页在 UNIX 程序员手册的版本中,我们看到.
并且..
已经存在:
按照惯例,每个目录中的前两个条目为“。”和“..”第一个是目录本身的条目。
至于其重要性,可以在以下网址找到答案:Panos 的回答。肯·汤普森解释了如何..
发生的1989 年采访:
每次我们创建一个目录时,按照惯例,我们会将其放在另一个名为目录 - 目录的目录中,即 dd。它的名字是 dd,所有用户目录以及实际上大多数其他目录,用户维护自己的目录系统,都有指向 dd 的指针,dd 缩写为“dot-dot”,dd 代表目录-目录。它是您可以访问系统中所有其他目录以维护这个意大利面碗的地方
当然,.
正如您所猜到的, 代表d
或短于directory
。此类目录本身自然与目录的实际名称共享相同的 inode 编号。现在,这仍然无法解释为什么目录.
链接到自身,但我有几个想法。
0.Unix 哲学:
在 1996 年由 Uresh Vahalia 出版的《UNIX Internals: The NEw Frontiers》一书中,第 8 章第 222 页指出:
Unix 支持每个进程的当前工作目录的概念,作为进程状态的一部分进行维护。这允许用户通过其相对路径名,它们是相对于当前目录进行解释的。
考虑到目录只是一种特殊的文件,我们需要一致的相对文件名来引用目录本身,这就是特殊的文件名.
,它是由d
目录的缩写演变而来的。
1.技术优势
我能想到的主要优点是系统可以简化 inode 查找,从而简化元数据信息。由于目录已经有一个包含.
相同 inode 的条目,因此无需通过完整路径进行查询。编程也是如此。考虑一个非常简单实现ls
.在那里我使用getcwd()
函数获取当前工作目录路径,然后将其传递给opendir()
。或者我可以扔掉getcwd()
直接使用opendir('.')
。在旧 PDP-11 终端时代,内存大小只有几千字节,节省系统调用开销至关重要。
2. 用户便利性:
请考虑以下示例:
mv ../filename.txt .
在里面Hendrik Jan Thomassen 的演讲有人提到,由于旧的终端键难以按下,原始的 Unix 命令很短,因此整天输入命令实际上是一项体力活。如果您深入目录树,重新输入当前工作目录的完整路径将非常繁琐。当然,mv
可以假设当我们这样做时,mv <file>
我们将目标暗示为“当前工作目录”。我只能猜测为什么mv <original> <new>
会盛行,也许是由于当时其他编程语言的影响。
3. 改进 MULTICS:
注意:我自己从未研究过 MULTICS,因此本文仅基于阅读在线资料
相对路径名可以以一个或多个小于字符(“<”)开头。
该>
字符在 MULTICS 上用作路径分隔符(就像/
在 Linux 上一样)。这可能看起来令人困惑。因此,./
当引用命令时,可以说更清楚 - 我们引用的是位于当前工作目录中的文件名。
这可能对其他命令有用。在 Unix/Linux 上创建文件的方法众所周知:touch ./file
。在 MULTICS 上,根据斯文森an
通过或命令完成add_name
:
cd foo
r 18:03 0.041 1
an foo bar
r 18:03 0.077 3
ls foo
Directories = 1.
sma foo
bar
r 18:03 0.065 0
附注:谈到以下内容时有明显的相似之处..
:向上导航一个目录是通过 完成的cwd <<
。
4. 引用可执行文件
如果你每天都运行脚本,那么你一定很了解./script.sh
语法。为什么很简单:shell 的工作方式是它在PATH
变量中查找可执行文件,因此当您提供./
它时,它不必在任何地方查找。PATH
变量的神奇之处在于它使您可以使用echo
而不是/bin/echo
或其他非常长的路径。现在假设您的路径中没有它script.sh
,并且它位于您当前的工作目录中。你现在做什么?输入/very/long/path/to/the/executable/this/typing/gets/exhausting/on/PDP-11/finally/script.sh
?这将抛弃所有 Unix 简单性的概念!所以回到 Unix 哲学,它也符合优雅设计/简单的原则。
当然,有些人想添加.
,PATH
但这实际上是非常糟糕的做法,所以不要这么做。
边注..
:和.
指向相同的 特殊情况是 inode 2 - /
dir ,这是有道理的,因为它是目录树中的最高点。当然,..
为 NULL 也可以,但让它指向/
自身更优雅。
关于链接数和目录硬链接的说明
作为吉尔斯正确指出(并引用乔治·乌德森), 目录的链接数从 2 开始(..
代表父目录和.
),所有附加链接均为子目录:
# new directory has link count of 2
$ stat --format=%h .
2
# Adding subdirectories increases link count
$ mkdir subdir1
$ stat --format=%h .
3
$ mkdir subdir2
$ stat --format=%h .
4
# Adding files doesn't make difference
$ cp /etc/passwd passwd.copy
$ stat --format=%h .
4
# Count of links for root
$ stat --format=%h /
25
# Count of subdirectories, minus .
$ find / -maxdepth 1 -type d | wc -l
24
直观地看,目录的链接仅为子目录 - 这是有道理的,因为硬链接与原始文件的时间相同。不过,这些并不是真正的硬链接 - 硬链接会创建一个指向相同数据。根据该定义,指向目录的硬链接将包含相同的数据,即包含相同的文件列表。如果删除指向目录的所有硬链接,这将导致文件系统出现循环或出现大量孤立文件。因此,不允许对目录创建硬链接并使用Gilles 的措辞来自另一个问题(我建议你阅读)“...事实上,许多文件系统确实在目录上有硬链接,但只是以非常有纪律的方式......”这些是.
和..
目录的特殊情况。
现在,问题变成了目录上下文中的“链接”实际上是什么意思? TL;DR:目录结构是一棵树,这里的链接表示每个树项的子节点数(每个叶子或没有子目录的目录只有 2 个链接)。具体来说,扩展和ext4使用 HTree 和軟體系用途B+ 树
结论
归根结底,原因.
在于它本身的设计很好。Unix 的最初作者可能在当时的技术限制下工作,但他们是当时最聪明的人,或者通常被称为“巫师”,他们做事是有原因的。
答案2
您的问题对我来说很模糊,但我尝试解释事情的工作原理,以便帮助您理解它。
系统中存储的每个文件都有一个编号(inode编号),让我们来看看:
$ ls -i -1 -a test/
9186865 .
9175041 ..
我曾经-1
在单列中显示文件列表并-i
显示 inode 和-a
显示隐藏文件。
每个文件都inode
保存有关文件的信息,例如权限、所有者、大小、链接数、修改时间、指向实际文件数据的指针(但不是文件的名称)。
每个目录不过是一个特殊的文件,包含名称(文件)列表以及与这些名称对应的 inode。
因此,当我删除文件(也称为取消链接文件)时,我会从其父目录中删除其链接,但数据仍然存在于磁盘上。
当您创建一个新目录时,默认情况下它包含 2 个硬链接,这意味着每个目录默认在其列表中 .
都有。..
您可能知道,.
这是一个到当前目录的硬链接,也是..
一个到父目录的硬链接,因此如果我创建一个新目录:
$ mkdir test
$ ls -i -d test
9186865 drwxrwxr-x 2 ravexina ravexina 4096 Sep 7 19:37 test
如您所见,链接数为 2,现在无论我在此目录中创建多少个文件,链接数都会保持不变,除非我开始创建目录。对于每个目录,数字将增加 1,现在您知道为什么了!因为每个新目录都包含指向其父目录的硬链接..
::
还记得我说过目录吗?
每个目录不过是一个特殊的文件,包含名称(文件)列表以及与这些名称对应的 inode。
链接实际上就是这些名称,每个文件默认都有 1 个链接(创建时的名称),现在如果您为此文件创建一个新的硬链接(意味着另一个名称,在另一个目录或指向相同数据 [inode] 的同一目录中),该数字将增加 1。
答案3
历史上,第一个 Unix 文件系统在每个目录中创建了两个条目:.
指向目录本身,并..
指向其父目录。这为应用程序和操作系统本身提供了一种遍历文件系统的简单方法。
因此,每个目录的链接数为 2+n,其中 n 是子目录的数量。链接是该目录在其父目录中的条目、目录自己的.
条目以及..
每个子目录中的条目。例如,假设这是以 为根的子树的内容/parent
,所有目录:
/parent
/parent/dir
/parent/dir/sub1
/parent/dir/sub2
/parent/dir/sub3
然后dir
的链接数为 5:dir
中的条目/parent
、.
中的条目以及、和中各/parent/dir
三个条目。由于没有子目录,其链接数为 2(中的条目和中的条目)。..
/parent/dir/sub1
/parent/dir/sub2
/parent/dir/sub3
/parent/dir/sub1
sub1
/parent/dir
.
/parent/dir/sub1
为了尽量减少根目录的特殊情况(因为没有“正确”的父目录),根目录包含一个..
指向自身的条目。这样,它的链接数也为 2 加上子目录数,2 为/.
和/..
。
后来的文件系统倾向于在内存中跟踪父目录,通常不需要.
和..
作为实际条目存在;典型的现代 unix 系统将.
和视为..
与文件系统类型无关的文件系统代码的特殊值。一些文件系统仍然包含.
和..
条目,或者假装包含和条目,即使磁盘上没有显示任何内容。
大多数文件系统仍然报告目录的链接数为 2+n,无论是否存在.
条目..
,但也有例外,例如 btrfs 就不会这样做。
现在尝试在评论中回答您的疑问:
这里列出的链接是什么?是文件本身吗?还是包含该文件的目录被列出?
该链接属于文件而不是目录,让我用一个例子来说明这一事实。现在如果我要做nano file.txt
,这里的链接将用于定位inode
该文件的编号,inode
随后将提供使程序能够修改该文件的信息nano
。请记住,保存inode
有关该文件的信息。(无论是文件夹、文件还是块设备)。
现在,每个文件名都必须链接到一个,inode number
才能对该文件执行正常操作,所以是的,该链接属于该文件,而不是父文件。我希望我正确理解了你的问题并回答了它。