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


20

这个问题很简单,但是我不确定在哪里查找,Google不会对句号和斜杠做出响应。

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

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


“请记住,这也在计算./和../目录”(除非它是“。”和“ ..”的错字。)
vonbrand

Answers:


15

Unix系统上的每个目录(可能还有其他所有系统)都至少包含两个目录条目。它们是.(当前目录)和..(父目录)。对于根目录,它们指向相同的位置,但与其他目录一样,它们是不同的。您可以使用此看到自己statpwdcd(在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
/
$

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

使用ls与管wc -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),而不是沦落成任何子目录。如果您不希望将任何点文件计入总数,只需将-A参数省略为ls


双方-a-A包含隐藏的,以及我已经意识到我想避免文件,所以顶多我会做ls -b | wc -l,但是这确实给了我正确的答案。我复制并粘贴的关于此命令的行是否不正确?如果正确,当目录中有6个文件或文件夹时,是否应该输出8?
2013年

@Adam是的,这可能会解决问题(“ ls -b | wc -l”);您还可以使用“ -1”(破折号+数字1)将列表强制置于单列中,而不是将所有列强制显示在一行中,但这在通过管道传递到另一个命令时仍然会发生。因此,(恕我直言)我将其保留为“ ls -1b | wc -l”;要进行“测试”,请运行“ ls -1b”并计算行数,然后运行“ ls -1b | wc -l”并验证结果。(这就是调试/测试管道的方法。)
迈克尔

@Sardathrion,该FAQ颇具误导性。Unix文件系统约定不是“奇怪的”;它们很常见的地方是另一个系统将它们拾取。但是没问题。然后,它说“ file命令使用幻数来标识...”,这是错误的:它也使用了许多启发式方法。在我的书中不是很可靠。
vonbrand 2013年

@vonbrand:足够公平,链接已删除。我只是略读了一下,看起来还不错。我知道我找到了一个不错的人,但现在不记得在哪里了。
Sardathrion-恢复莫妮卡

1
你误会了: 。..和..是1970年代UNIX的历史性人工制品,是从没有mkdir()系统调用的时候起产生的。并非所有文件系统都具有它们,并且POSIX甚至也不需要它们。
schily

6

要回答主题中的问题:

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

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

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

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

不过要当心: /a/b/../c可能与/a/c因为/a/b可能是一个不一样指向其他目录符号链接不同。

一个例外是,当该路径被赋予cd某些外壳程序的命令时。那些cd.. 逻辑上忽略..目录中的条目。您经常看到cd -P使用正确编写的脚本来禁用该功能的原因,否则可能导致混乱和不一致。

要计算不包括当前目录条目的数量...bash,你可以这样做:

shopt -s nullglob dotglob
set -- *
echo "$#"

使用zsh:

f=(*(ND))
echo $#f

便携性:

find . ! -name . -prune -print | grep -c /

我有点困惑;您列出的所有三个都将实际计数加一。例如,如果我有6个文件或文件夹目录,他们的输出7,不要6.对我来说,好像ls | wc -l是唯一一个不包括...
亚当

1
@Adam,ls不列出隐藏文件。您需要ls -A获得与那些相同的东西。如果你不想算上隐藏文件,起飞的dotglob(对于bash)或D(对于zsh中)或添加! -name '.*'之前-print进行find
斯特凡Chazelas

是的,我实际上在列出文件后才注意到这一点。您知道吗,为什么ls | wc -l还给我正确的答案并排除隐藏文件...
2013年

1
亚当,在您的目录中,您有个...另一个文件的名称.以ls 开头,而不会以ls列出ls -A。因此ls | wc -l,由于它没有计算该隐藏文件,因此无法为您提供正确的答案。
斯特凡Chazelas

1
是的,.并且..是隐藏文件,因为它们以开头.。甚至有一个传说可以解释点文件是偶然被隐藏的,因为的早期实现ls本意是仅将.和排除在外..,但是存在一个错误导致该点文件排除了以开头的任何文件.ls | wc -l如果文件名包含换行符,则无法使用。
2013年

1

我不是一名出色的Linux专家,但是我知道Linux(16年前曾在Slackware上担任管理员:)

./和../目录很简单:是当前目录,..是上一个目录(在pwd的树中-local directory命令-

如果算在内的话,我认为它们会在清单总数中加2,而不是真正递归地计算当前目录下的目录,并再次计算当前目录(。):))

所以基本上我认为它将值2添加到当前目录中已经计数的(文件)。

如果我错了,任何人都可以纠正我。

我只是在发布帮助,看到这里没有人回答这个问题,他们可能很忙。但是,只需进行实验,看看是否有10个文件,并且计数为12,就这样。


是的,Adrian是正确的:。是当前目录,..是层次结构中紧接上方的目录。
schaiba 2013年

..并不总是引用树中的上一个目录:在“ /”中,..也引用当前目录。
Bonsi Scott

因为您可能位于文件系统的/ root目录中?
Adrian Tanase

如果将两个添加到目录中的#个文件中,为什么在osx的终端中对其进行测试时我得到正确的答案?例如,包含6个文件或文件夹的目录在执行时将输出6,而不是8ls | wc -1
Adam

我意识到这是因为它们包含隐藏文件(即.ds_store),但我仍然看不到ls | wc -l包含方式.以及..何时获得正确答案,而不是正确答案+ 2。–
亚当
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.