awkによってlsの表示結果を改変してみた

 Zshのalias機能を使ってlsの表示結果に手を加えていたら、lsのオプション引数によって設定しうるもの以外の体裁が気になるようになった。とりわけ、アクセス権限を数値で表示したい。そこで、awkを使ってlsの表示結果を改変することにした。

 改変前のlsの表示結果は次の通りである。

f:id:blechmusik2:20130723223928p:plain

 awkを使って以下の三つを実現したい。

  • アクセス権限の状況を数値で示す
  • シンボリックリンク先がディレクトリならば、ファイルでは無くディレクトリのグループとして分類する
    • あらかじめ、.zshrc に alias ls="ls --classify" を設定しておく
  • ディレクトリとファイルを順にまとめて表示する

 awkを使って手を加えたlsの表示結果はこのようなものだ。

f:id:blechmusik2:20130723223941p:plain

 思ったように改変ができたようだ。

 件のawkソースコードを貼り付けておこう。

#!/usr/bin/awk -f
BEGIN {
    list["info"] = "";
    list["directory"] = "";
    list["file"] = "";
}

{
    if (1 < NR) {
        mod = "";

        # [r w x r w x r w x]
        # => [[r w x] [r w x] [r w x]]
        # => [~ ~ ~]
        # => [~~~]
        split(substr($1,2,length($1)), table, "");

        for (i = 0; i <= 2; i++)
        {
            mod_number = 0
            for (j = 1; j <= 3; j++)
            {
                table_index = (3 * i) + j
                status = table[table_index]

                if ("r" == status) {
                    mod_number += 2 ^ 2;
                } else if ("w" == status) {
                    mod_number += 2 ^ 1;
                } else if ("x" == status) {
                    mod_number += 2 ^ 0;
                }
            }
            mod = mod "" mod_number;
        }
        
        $1="[" toupper(substr($1,0,1)) "] " mod;

        $2=$3=$4="";

        $5= $5 "\t";
    }


    if (1 == NR) {
        list["info"] = $0
    } else if ($NF ~ /\/$/) {
        list["directory"] = list["directory"] "\n" $0
    } else {
        list["file"] = list["file"] "\n" $0 
    }
}

END {
    print list["info"] list["directory"] list["file"]
}


この awk スクリプトを zsh のグローバルエイリアス機能によって使いやすくしてみようか。

alias -g @@=" | awk -f ~/test.awk"