プログラミング言語 Standard ML 入門 (問題の解答例)
17 OSとのインターフェイス

17.2 ディレクトリとファイルの操作

問 17.1

上記の ls 関数を改良し,各ファイルごとに, ファイルの種類(ディレクトリ,リンク,通常ファイル),ファイルのアクセス (読み出し可,書き込み可,実行可),最終更新年月日,ファイルサイズを以下の ような形式で表示するようにせよ.

   - ls();
   dlrwx            file size       last modified            file name
   d-rwx                 4096        Mar 19 10:50             examples
   --rw-                18666        Apr  8 09:39               ml.tex
   --rw-               257094        Mar 18 16:40            part1.tex
   --rw-               186111        Apr 16 10:58            part2.tex

先頭の dlrwx はそれぞれ,ディレクトリ,リンク,読み込み可,書き込み可, 実行可を表す.

解答例 

   fun ls () =
       let
         val d = F.openDir (F.getDir())
         fun printRest () =
             case F.readDir d of
               NONE => F.closeDir d
             | SOME f =>
               let
              val size = F.fileSize f
              val time = Date.toString (Date.fromTimeLocal (F.modTime f))
                 val modString = implode
                                   [if F.isDir f then #"d" else #"-",
                                    if F.isLink f then #"l" else #"-",
                                    if F.access (f, [F.A_READ]) then #"r" else #"-",
                                    if F.access (f, [F.A_WRITE]) then #"w" else #"-",
                                    if F.access (f, [F.A_EXEC]) then #"x" else #"-"]
            in
                 (Format.printf
                    "%10s%15d%30s%30s\n"
                    [Format.S modString,
                     Format.I size,
                     Format.S time,
                     Format.S f
                    ];
               printRest())
            end
       in
         (Format.printf
            "%10s%15s%30s%30s\n"
            [Format.S "dlrwx",
             Format.S "file size",
             Format.S "last modified",
             Format.S "file name"
            ];
          printRest()
         )
       end
問 17.2

copy 関数が,ファイルおよびディレクトリの更新日付を保存する ように変更せよ.

解答例  copy関数にF.setTimeコマンドを追加すればよい。 変更例を以下に示す。

   fun copy a b =
       if not (F.isDir a) then
         (copyFile a b;
          F.setTime (b,SOME (F.modTime a)))
       else
         let val d = F.openDir a
             fun copyDirStream d b =
                 case F.readDir d of
                   NONE => F.closeDir d
                 | SOME item =>
                   let val from = P.concat (a,item)
                       val to = P.concat (b,item)
                   in (copy from to;copyDirStream d b)
                   end
         in
           (F.mkDir b;
            copyDirStream d b;
            F.setTime (b,SOME (F.modTime a)))
         end