「tacコマンド(catの反対だからtac)の新たな使い方を知った。」の意味

こんにちは。moldがカビという意味なのをさっき知ったまるりんです。

Twitterで流れていたこの文章、正直意味を理解できませんでした。今回はこの発言の意味を読み解いていきます。

macにtacがインストールされてなかったのでおもむろにUbuntuのコンテナに入ります。 Ubuntuのコンテナには最初からtacがインストールされているようです。

$ docker run -it ubuntu bash
# tac --version | head -1
tac (GNU coreutils) 8.30

まずtacを実行してみます。ファイルの最終行から開始行に向かって表示していくようです。

# cat > hoge.txt
abc
def
ghi
# tac hoge.txt 
ghi
def
abc

さて、Ruiさんの言っている「コマンドfooの出力を全部バッファリング」とはどういう意味なのでしょうか。 よく考えた結果、tacはfooのすべての出力をメモリに持っているのではないかと思えてきました。 tacが出力を開始できるのはfooの出力を最後まで読み切ってからです。 したがってtacが入力をメモリに保存している、あるいはファイルに書き出すかしない限り最終行から開始行に向かって出力できないと思います。 これを検証するには大きな入力をtacに渡してメモリ消費量が大きく増えるのかを確認します。

# seq -f '%01023g' 1 $(expr 10 "*" 1024 "*" 1024) | tac | tac > /dev/null &
[1] 11
# free -h -c100
              total        used        free      shared  buff/cache   available
Mem:          1.9Gi       345Mi       1.0Gi       243Mi       573Mi       1.2Gi
Swap:         1.0Gi       207Mi       816Mi

              total        used        free      shared  buff/cache   available
Mem:          1.9Gi       345Mi       421Mi       243Mi       1.2Gi       1.2Gi
Swap:         1.0Gi       207Mi       816Mi

              total        used        free      shared  buff/cache   available
Mem:          1.9Gi       347Mi        65Mi       242Mi       1.5Gi       1.2Gi
Swap:         1.0Gi       207Mi       816Mi

              total        used        free      shared  buff/cache   available
Mem:          1.9Gi       347Mi        81Mi       242Mi       1.5Gi       1.2Gi
Swap:         1.0Gi       208Mi       815Mi

freeが大きく減ってbuff/cacheが大きく増えているのが分かります。挙動からtacが入力をメモリに記憶していると想定できます。 したがって仮説が正しいと分かりました。 しかし、入力を全部バッファリングすることの活用方法は分かりませんでした。