Macの容量を空けるためにTerminalで容量の大きいディレクトリやファイルを調べたいだけなんだが

Macの容量を空けるためにTerminalで容量の大きいディレクトリやファイルを調べたいだけなんですが、理想的な方法がパッとわからなかったので、そのへんの知見を公開しておきます。

# 結論

この手の書き物のルールに従って、最初に結論を述べますね。

```
$ shopt -s dotglob
$ sudo du -sh (target)/* | sort -h
```

これが良いと思います。

一行目の`$ shopt -s dotglob`は最初に一回だけ実行すればOKです。
二行目の`(target)/*`の部分は、`~/Documents/hogehoge/*`など、ターゲットとするディレクトリによって書き換えてください。

その場合はこうなります。

```
$ sudo du -sh ~/Documents/hogehoge/* | sort -h
```

カレントディレクトリなら

```
$ sudo du -sh ./* | sort -h
```



# 理想


この記事では、次の条件を満たすようなターミナルコマンドを「理想」としますね。


ディレクトリXの配下にあるディレクトリやファイルについて容量を調べたいとします。

 - 結果は小さい順にソートして表示する
 - 容量は人間に読みやすい形式で表示する
 - システムファイルの容量も表示する
 - Xの直下にあるディレクトリとファイルの両方を表示する
 - Xの直下より深い階層にあるファイルやディレクトリは結果に表示しない
 - 隠しファイルや隠しディレクトリ(名前がドットから始まるもの)も表示する

これらを理想とする理由を説明します。

### 結果は小さい順にソートして表示する
Terminalでコマンドを実行した結果は、ズラッと画面に表示されて結構見づらいです。

大きい順にソートしてしまうと、容量の大きいものを見つけるために上までスクロールしなければいけなくなります。

小さい順なら、実行結果の一番下に一番大きいものが来るのでパッと見でわかります。

### 容量は人間が見やすい形式で表示する

私が人間だからです。

### システムファイルの容量も表示する

システムファイルの中にも無駄に容量の大きい奴がいる可能性は大いにあります。

消していいかどうかしっかり調査した上で、いらない奴は消していきたい。

### Xの直下にあるディレクトリとファイルの両方を表示する

ファイルを表示しないものは論外です。容量の大きいファイルが見つけられなくなるので。

ディレクトリ単位のものはなぜ欲しいかというと、一つのディレクトリに大量のファイルがあって容量が大きくなっているようなケースがよくあるからですね。そういう場合はディレクトリの中身をまるごと消したいわけです。

### Xの直下より深い階層にあるファイルやディレクトリは結果に表示しない

同上です。ディレクトリを掘り下げて小さいファイルを大量に表示した結果、ディレクトリの単位での容量がわからなくなっては困ります。

### 隠しファイルや隠しディレクトリ(名前がドットから始まるもの)も表示する

隠しファイルが容量を食ってる場合もあるかもしれません。こちらとしてはとにかく全部調べたいので。


# 理想の実現方法

そもそも使うコマンドは

```
$ du
```

一択です。

これにどんなオプションなどを付ければ実現できるか考えます。

##簡単に実現できる組

### 結果は小さい順にソートして表示する

```
| sort -h
```

をつければOK。もし万が一逆順にしたい人は、`sort`に`-h`だけではなく`-r`オプションも付けましょう。

### 容量は人間が見やすい形式で表示する

```
-h
```

オプションをつければOK

### システムファイルの容量も表示する

頭に`sudo`を付ければOK。これがないと`Permission denied`エラーが出て中身を調べてくれなくなることがよくあります。

また、最近(執筆日：2019-02-11)の`Mac OS X`では`Operation not permitted`エラーが出る可能性があります。この件については後述します。

##簡単に実現できない組について

残る3つの「理想」を同時に全て実現しようとした時に、困りました。うまい方法がなかなか見つからなかったです。

 - Xの直下にあるディレクトリとファイルの両方を表示する
 - Xの直下より深い階層にあるファイルやディレクトリは結果に表示しない
 - 隠しファイルや隠しディレクトリ(名前がドットから始まるもの)も表示する

これらを実現するには、次のようなオプションやワイルドカードを使うのが良さそうです。

ところが、それぞれに欠点があります。

###`-a`

ディレクトリだけではなくファイルも表示しますが、直下より下の階層まで掘り下げてしまいます。

###`-d1`

掘り下げを1回層に制限しますが、ディレクトリのみ表示され、ファイルが表示されないです。

###`-s (target)/*`

このようにワイルドカードを使うことで、掘り下げを1回層に制限し、かつ、ファイルもディレクトリも表示されますが、隠しファイルや隠しディレクトリが表示されないです。


###併用できない

じゃあこれらをうまく組み合わせればなんとかならないか、と考えたのですが…


```
$ sudo du -d1 -a -h (target) | sort -h
```

などとすると、次のように怒られてしまいます。

```
usage: du [-H | -L | -P] [-a | -s | -d depth] [-c] [-h | -k | -m | -g] [-x] [-I mask] [file ...]
```

`-a`と`-s`と`-d`が同じ四角カッコの中に入ってますね。つまり、併用できないらしいです。えええええええ

##ワイルドカードで隠しファイルも出るようにする

```
-s (target)/*
```

これが一番惜しかったですね。これで隠しファイルや隠しディレクトリも出てくれれば良いですね。

### グロブの設定を変える

Terminalコマンドでよく使うワイルドカード`*`などの仕組みをグロブと言います。(正規表現ではありません！)

グロブ→https://ja.wikipedia.org/wiki/%E3%82%B0%E3%83%AD%E3%83%96

これが、デフォルトでは、`*`が隠しファイル・隠しディレクトリにマッチしないような設定になっているんですね。

だから、`-s (target)/*`で隠しファイル・隠しディレクトリが表示されてくれないわけです。

```
$ shopt -s dotglob
```

とすると、その設定を変えることができます。もとに戻すには

```
$ shopt -u dotglob
```

です。`-s``-u`はそれぞれset, unsetの意味だと思います。

#結論

ということで、長くなりましたが結論を再掲します。

```
$ shopt -s dotglob
$ sudo du -sh (target)/* | sort -h
```

一行目の`$ shopt -s dotglob`は最初に一回だけ実行すればOKです。



#Operation not permitted エラー

このエラーが出た場合は、

System Preferences(システム環境設定)を開いて

Security & Privacyを選んで

Privacyタブから、

Full Disk Access権限をTerminalに与えれば~~解決します。~~

解決すると思ってたんですが、しませんね。一旦、要調査としておきます…。

このエラーが出るのは一部のディレクトリ・ファイルだけなので、致命的な影響はないと思うけど、該当ファイルの容量が大きくないかどうか確信がないので気持ち悪いですね…。