Real world OCaml
For many tasks, I find OCaml as useful as Python and like "a better C".
This program matches files in a directory with a provided suffix and invokes a program on them.
This program matches files in a directory with a provided suffix and invokes a program on them.
(*e.g.
Match files in directory with given suffix and invoke a program on
them.
$ ./build/bin/filesin.exe -d \
c:/project/examples -p \
c:/project/someprog.exe
*)
(*Globals*)
let version,root,prog,suffix=ref false,ref "",ref "",ref ""
let (read_args:unit -> unit) = fun () ->
let specification =
[("-v", Arg.Set version, "Print the version number") ;
("-d", Arg.String (fun s -> root := s), "Directory") ;
("-s", Arg.String (fun s -> suffix := s), "Suffix") ;
("-p", Arg.String (fun s -> prog := s), "Path to the prog") ;
]
in Arg.parse specification
(fun s -> Printf.printf "Warning : Ignoring unrecognized argument \"%s\"\n" s)
("Usage : "^(Sys.argv.(0))^" options")
let (filesin:string -> string array option) = fun s ->
if not (Sys.file_exists s)
|| not (Sys.is_directory s) then
None
else (Some (Sys.readdir s))
let (read_and_close:Unix.file_descr -> string) = fun fdr ->
let buf = Buffer.create 1024 in
let bytes_to_read = ref true in
while !bytes_to_read do
let s = String.create 1024 in
let num_bytes_read = Unix.read fdr s 0 124 in
Buffer.add_string buf (String.sub s 0 num_bytes_read) ;
if num_bytes_read < 1024 then bytes_to_read := false ;
()
done ;
Unix.close fdr ;
Buffer.contents buf
let (process_file:string -> unit) = fun f ->
let p = Filename.concat (!root) f in
let cmd = Printf.sprintf "%s -l -e %s" (!prog) p in
(*I tried to use anonymous pipes here but that seems broken on
Windows when [Unix.system] is involved*)
let tf=Filename.temp_file "tmp" "" in
let fdw = Unix.openfile tf [Unix.O_WRONLY; Unix.O_TRUNC; Unix.O_CREAT] 0o666 in
let tmp = Unix.dup Unix.stdout in
let stat = (
Unix.dup2 fdw Unix.stdout ;
Printf.printf "\n*** - %s:\n" p; flush stdout;
Unix.system cmd (*Invoke the intpreter on f*)
)
in
Unix.dup2 tmp Unix.stdout ; Unix.close tmp; Unix.close fdw;
match stat with
| Unix.WEXITED 127 ->
Printf.printf "The command \"%s\" could not be executed" cmd
| _ ->
let fdr = Unix.openfile tf [Unix.O_RDONLY] 0o666 in
Printf.printf "%s" (read_and_close fdr) ; flush stdout (*; Sys.remove tf*)
let (process_files:string list -> unit) = fun fs ->
List.iter (fun f -> process_file f) fs
let (main:unit) =
read_args () ; Printf.printf "%s" !prog ;
if !version then print_string "0.0.0\n"
else
if !suffix = "" then
raise (Failure
"Missing argument : suffix") ;
if not (Sys.file_exists (!prog)) then
raise (Failure (Printf.sprintf
"Bad argument : The file '%s' does not exist" !prog)) ;
try
match (filesin !root) with
| Some names ->
let n=String.length !suffix in
let pred e =
let i = (String.length e - n) in
(i >= 0) && (String.sub e i n) = !suffix
in process_files (List.filter pred (Array.to_list names) )
| None -> ()
with
| _ as e -> Printf.printf "Exception : %s\n" (Printexc.to_string e)