ensure-directories-exist注意書き

ensure-directories-existは、pオプション付きのmkdirコマンドと同じような動作をすると思っていたのだが、少し違ったのでメモ。


mkdirコマンドは、引数のパスをディレクトリ名として解釈する。※以下の例では、全て空の/tmpディレクトリのみが存在すると仮定している

# 下の二つのコマンドは、どっちも同じディレクトリを作成する
> mkdir -p /tmp/dir/
> mkdir -p /tmp/dir


対して、ensure-directories-exist関数は、第一引数をpathname型に変換してから、そのディレクトリ部分を取り出し、処理する。

;; mkdirと同じ結果
> (ensure-directories-exist "/tmp/dir/")
--> "/tmp/dir/"
    t

;; mkdirと異なる結果
> (ensure-directories-exist "/tmp/dir")
--> "/tmp/dir"
    NIL  ; dirディレクトリは作成されない

;; 末尾に"/"がつくかつかないかで、pathnameの解釈が異なる
> (pathname-directory (pathname "/tmp/dir"))
--> (:ABSOLUTE "tmp")       ; "dir"はファイル

> (pathname-directory (pathname "/tmp/dir/"))
--> (:ABSOLUTE "tmp" "dir") ; "dir"はディレクトリ

要は、ensure-directories-existにディレクトリ名を渡す場合は、末尾に必ず"/"がつくように気をつけましょう、ということ。
この(末尾に"/"がないとファイル名として認識するという)動作は、他のpathnameを引数に取る関数と同じものなので、分かってみれば納得なのだが、なかなか気がつかなかった。