awk 演習: realpath を実装2009年03月21日 13時34分23秒

realpath(3) は C 言語の関数だ。FreeBSD はそれを呼ぶコマンド realpath(1) もある。Linux でシェルスクリプトから呼べないので、awk で簡単に仕立て上げた。

/./ がパスに含まれていたら無視、/../ がパスに含まれていたら、/ のルートパスを突き抜けない限り、一番最後の項目を削除する。基本的に先入れ後出しの FILO なので、スタックを用いた実装が適している。


% cat realpath.awk
BEGIN{FS="/"; path[1] = ""}
{ idx = 1;
  for(i = 1; i <= NF; i++)
  {
    if($i == "") ;
    else if($i == ".") ;
    else if($i == "..")
    {
      if(idx > 1)
        delete path[idx--];
    }
    else
      path[idx++] = $i
  }

  if(idx == 1)
    print "/"
  else
  {
    full = "";
    for(i = 1; i < idx; i++)
      full = full sprintf("/%s", path[i]);
    print full;
  }
}

こんな感じの入出力になる。


% cat input.txt
/
/a
/b/c
/d/..
/e/../
/f/../g
/h/../../i
/.
/j/.
/k/./
/l/./m
/n/././o
% cat input.txt | awk -f realpath.awk
/
/a
/b/c
/
/
/g
/i
/
/j
/k
/l/m
/n/o