

Unix / Linux の世界で、ファイルシステム上の全てのディレクトリ上に `.` と `..`
はわざわざ確認しなくても「概念上」存在するものだと思っています。どこのディレクトリに `cd` しても存在することがわかりきっているのに `ls -a` が
`.` や `..` を表示するのはちょっと無駄なような気がしてきました。

なぜ `ls -a` は `.` と `..` を表示するんでしょうか？

関連質問  
[findコマンドで特定のディレクトリの全てのディレクトリを表示する方法](https://ja.stackoverflow.com/questions/41551/)


CC BY-SA 3.0
2018-02-08T02:28:20.710
41558
2018-02-08T16:09:18.847
8589
question
linux unix
`ls -a` はなぜ `.` や `..` を表示するんでしょう？


概念上ではなく、lsなどのユーザープログラムから見ると実際に存在するからではないかと。

lsでは、`-a`のかわりに`-A`が指定されると、プログラム中で意図的に“.”“..”を除外して表示します。


CC BY-SA 3.0
2018-02-08T03:09:16.580
41561
2018-02-08T03:09:16.580
4010
41558
answer


直接「なぜ」への回答ではないですが投稿してみます。  
lsコマンドの[ソース](http://git.savannah.gnu.org/gitweb/?p=coreutils.git;a=blob;f=src/ls.c;h=cd6b09c8e847a6031ec9a6c75c169f446ca9b61b;hb=HEAD)を見てみると、ファイルのリストは`readdir`を呼び出して生成しているようです。gnuの[ドキュメント](https://www.gnu.org/software/libc/manual/pdf/libc.pdf)(p.404)にはこんなことが書いてあります。

> ### struct dirent * readdir(DIR *dirstream)
>
> Portability Note: On some systems readdir may not return entries for . and
> .., **_even though these are always valid file names in any directory_**.

`readdir`は実装によっては`.`や`..`を返さないことがあるようです。lsコマンドを書いた方が実装依存の処理を書かないようなポリシーに従っていると仮定すれば、「ちょっと無駄」かどうかを判断したのは`readdir`を実装した方ということになりますね。  
では`readdir`がなぜこれらを返すのか（あるいは場合によっては返さないのか）については……ちょっとみつかりませんでした。無いよりあったほうがAPIとしてはより汎用性があるから、かもしれません。


CC BY-SA 3.0
2018-02-08T03:33:53.353
41565
2018-02-08T03:33:53.353
41558
answer


なぜ表示されるかと言えば **ハードリンクとして**
実際に`.`や`..`という名前でディレクトリが存在しているからのようです。「inode」を確認すると、ディレクトリ名で指定した場合と`.`とで必ず一致しています(`..`も同様)。

[code]

    # ls -id /root
    3112961 /root/
    # ls -id .
    3112961 ./
    
    # cd /tmp
    # ls -id /tmp
    1703937 /tmp/
    # ls -id .
    1703937 ./
    
[/code]

* * *

なお、`ln`コマンドでハードリンクを作ろうとしても、ユーザがコマンドで実行した場合はディレクトリに対しての作成は禁止されていますし、スーパーユーザー権限向けのオプションが存在しますがこちらも実際に試すとエラーになります(セキュリティ上の理由？)。

>
[code]

>        -d, -F, --directory
>               スーパーユーザーがディレクトリへのハードリンクを作成するのを許す。
>  
[/code]

ディレクトリ作成時、コールバック経由で`.`や`..`のハードリンクが作成されているようです。  
(下記リンク先はext2での説明)

参考：  
[親ディレクトリ/カレントディレクトリ - Linuxの備忘録](http://wiki.bit-
hive.com/north/pg/%BF%C6%A5%C7%A5%A3%A5%EC%A5%AF%A5%C8%A5%EA%2F%A5%AB%A5%EC%A5%F3%A5%C8%A5%C7%A5%A3%A5%EC%A5%AF%A5%C8%A5%EA)


CC BY-SA 3.0
2018-02-08T05:32:21.737
41566
2018-02-08T05:32:21.737
3060
41558
answer


### `.` 始まりのファイルが「隠しファイル」となった経緯

そもそも、`ls` に無視されるのが `.` と `..` だけで無く `.`
で始まるファイル全てであるのは、UNIX開発初期に生まれてしまったバグだそうです。

> It was in assembler then, but the code in question was equivalent to
> something like this:
[code]

>     if (name[0] == '.') continue;
>  
[/code]

>
> This statement was a little shorter than what it should have been, which is
[code]

>     if (strcmp(name, ".") == 0 || strcmp(name, "..") == 0) continue;
>  
[/code]

>
> —— [A lesson in
> shortcuts.](https://plus.google.com/u/0/+RobPikeTheHuman/posts/R58WgWwN9jp)

このバグを多くの開発者が引き継ぎ、ついには「隠しファイル」という概念や、設定ファイルを隠しファイルにするという習慣が生まれました。

### 開発者の意図の推測

ここからは推測です。  
`ls` に `-a` オプションが追加された時点では、設定ファイルの名前を `.`
で始めてホームディレクトリ直下にばらまくという習慣が定着していなかったのではないでしょうか。  
だとすれば、UNIX開発者が `-a` を追加した意図は、「設定ファイルも含めて表示する」では無く、「ショートカットを表示する」だったことになります。  
「ほぼ使わないけれど、`.` と `..`
というショートカットが確かに存在することを示すのに使うオプション」くらいの位置付けだったのかも知れません（ショートカットは今にいたるまで `.` と
`..` だけですが、確認が必要になるくらい追加する可能性も考えていたかも知れませんね）。


CC BY-SA 3.0
2018-02-08T16:09:18.847
41590
2018-02-08T16:09:18.847
3054
41558
answer