什么是 ./ 和 ../ 目录?

Ada*_*dam 23 directory filenames

一个简单的问题,但我不知道在哪里看,谷歌不响应句号和斜线。

我只是想计算当前目录中文件和目录的数量(不包括子文件夹/文件)并试图区分ls -1 | wc -lls | wc -l因为它们看起来相同。我正在查看的一个网站说“请记住,这也计算了 ./ 和 ../ 目录。” 关于带有 的那个ls -1,我不确定这是否意味着它包含之前的目录或其他内容(我不想要的),但它似乎没有从测试中做到这一点。

有人可以确认其中哪一个最适合仅计算当前目录中的文件和目录数量(而不是子目录)以及它们对 ./ 和 ../ 目录的含义?

use*_*ser 20

Unix 系统上的每个目录(也可能是每个其他系统)至少包含两个目录条目。它们是.(当前目录)和..(父目录)。在根目录的情况下,它们指向同一个地方,但对于任何其他目录,它们是不同的。您可以使用stat,pwdcd命令(在 Linux 上)亲自查看:

$ cd /
$ stat . .. bin sbin | grep Inode
Device: 802h/2050d      Inode: 2           Links: 27
Device: 802h/2050d      Inode: 2           Links: 27
Device: 802h/2050d      Inode: 548865      Links: 2
Device: 802h/2050d      Inode: 2670593     Links: 2
$ pwd
/
$ cd ..
$ pwd
/
$
Run Code Online (Sandbox Code Playgroud)

请注意,binsbin每个人都有两个链接到它。一个是根目录中的目录条目,另一个是该.目录内的条目。

使用ls管道 towc -l是计算 ls 输出中行数的简单技巧。假设是每个文件或目录将在输出中恰好占据一行。当输出是非终端时,GNU ls 将自动执行此操作;其他人可能需要-1选择显式开启行为。wc -l简单地计算并输出-l其输入中的行数 ( )。

这种方法的问题在于,在 Linux 和传统上用于 Linux 的文件系统上,文件和目录名称(在这方面它们实际上是相同的)允许包含换行符。在这些情况下,任何一种方法都会失效——这些条目将被视为两个或多个条目,而实际上它们是一个条目。

只要您使用 GNU ls,没有名称包含换行符的目录条目,并且没有奇怪的别名ls(例如,ls -a),两者都会输出当前(或指定)目录中的文件和目录的计数。对于大多数人来说,这已经足够了,但在一般情况下是无效的。

如果您需要正确处理目录条目名称中的异常字符(主要是换行符),我建议使用 ls 的-b选项来转义它们。ls -1bA将在其自己的行上打印每个目录条目名称,转义异常字符(因此每个目录条目将被视为一个),包括任何点文件和 -directories。钉在wc -l一个完整的命令行ls -1bA | wc -l上,就会在当前目录下的文件和目录的数量(但忽略...;这之间的区别-a-A),而不是沦落成任何子目录。如果您不希望将任何点文件计入总数,只需-Als.


Sté*_*las 7

回答题目中的问题:

当在Unix中创建一个目录B,将其添加为新条目到另一个目录A(它的父目录),并在B,两项相加:一个叫.作为硬链接本身,和一个叫..作为硬链接到 A。

这些是唯一允许的目录硬链接(尽管某些 Unices 的某些旧版本也允许任意链接)。

这就是为什么对于大多数文件系统(btrfs一个明显的例外),links目录的数量表示它有多少个子目录(考虑到它们的..条目)。

当您重命名/移动目录时,如果它位于同一目录(以不同的名称),则只会A更改其中的名称条目。B的.,并..不会受到影响。但是如果你移动它做一个不同的目录,那么..inB就会改变。这解释了为什么您可以重命名您没有写访问权限的目录(假设您对父目录有写访问权限),只要您不将其移动到另一个目录(否则需要更改..条目会阻止你从移动它)。

但要注意: /a/b/../c可能与/a/c因为/a/b可能是指向其他目录的符号链接不同。

一个例外是当该路径被提供cd给某些 shell的命令时。这些cds 在.. 逻辑上忽略..目录中的条目。您经常cd -P在正确编写的脚本中看到禁用该功能的原因,否则可能会导致混淆和不一致。

要计算当前目录中排除...with的条目数bash,您可以执行以下操作:

shopt -s nullglob dotglob
set -- *
echo "$#"
Run Code Online (Sandbox Code Playgroud)

使用 zsh:

f=(*(ND))
echo $#f
Run Code Online (Sandbox Code Playgroud)

便携:

find . ! -name . -prune -print | grep -c /
Run Code Online (Sandbox Code Playgroud)