A lightweight utility module for shell scripting with ocaml, both as a top-level script interpreter and to compile the scripts if you like (no support for compilation, just use ocamlbuild, it's easy) Just drop the shell_utils.ml file into same directory as your script, add a few lines to header and get going. See more under INSTALL.txt and the install.ml file for a basic example. NOTE: The script has not been tested on Windows, but the code is in place. Please report if you have any issues. The module provides cross platform versions of cp, cp_r, rm, rm_rf, mv, mkdir, mkdir_p, cd, pwd, ... and variants cp', mv', ... that operate on source lists Commands do not take glob patterns. Commands will quote path names if implemented by external shell commands. Use list variants of commands to use globbing, like cp' (glob "*/test?dir/*.tst") "targetdir" Commands mv x y -> () move the file or directory x to y if y is an existing directory move source inside y mv' xs y -> move the files and directories in the list xs to the target directory y cp x y -> () copy file x to target y, y can be a file or a directory cp' xs y -> () copy list of source files to target directory y cp_r x y -> () copy file or directory x to target file or directory y cp_r' xs y -> () copy list of files or directories xs to target directory y mkdir x -> () x is an unquoted directory to be created fails if directory exists, depending on platform fails if parent directory does not exist mkdir' xs -> () applies mkdir to each element in the list xs mkdir_p x -> () creates a directory and any necessary parent directories does not fail if directory exists mkdir_p' xs -> () applies mkdir_p to all elements in the list xs rm x -> () remove the file x rm' xs -> () remove all files in the list xs rmdir x -> () remove the empty directory x, fail if directory is not empty rmdir' xs -> () remove all the empty directories in the list xs, fail if any directory is not empty rm_rf x -> () remove the file or directory x, even if non-empty or read-only rm_rf' xs -> () remove all the files and directories the file or directory x, even if non-empty or read-only touch x -> () create file x or modify time stamp if it exists touch' xs -> () create or modify time stamp of all files in the list xs Reporting and error handling: echo msg -> () print message to stdout wihtout any newline echo' msgs -> () print all messages to stdout with no separator in between and no terminal newline echoln msg -> () print msg to stdout and add a terminal newline echoln' msgs -> () print all messages to stdout with no separator in between and add a terminal newline echoln'' msgs -> () print all messages to stdout with a newline after each message error msg errorcode -> () print the msg to stderr and exit with errorcode don't exit if error code is 0 Test functions: test for file and directory presence (anything not missing and not a directory, is a file in this context) exists -> bool (file or directory is present) isdir -> true of directory, false if missing or a file isfile -> true of file, false if missing or a directory test_e -> same as exists test_d -> same as isdir test_f -> same is isfile ftype path -> "f" | "d" | "" Globbing: Globbing is not integrated with shell commands, but you can iterate over commands by globbing a file list using List.iter for example. See also globbing examples in test.ml Warning: this is new globbing code, globing can do things to your file system it probably works in mist cases, but test it first glob path -> string list Understands unix style shell globbing with wildcards of *, ~ and ? Operates like 'ls -d': ls * does not list content of immediate subdirectories. Does not handle escaped paths like glob "\~". ~ (should) also work on Windows via the home () function. Example: mkdir_p "dist"; List.iter (fun f -> cp f "dist") (glob "~/test_*/_build/x*.cm?");; echoln "current directory:" echoln (quote' (glob "*"));; glob' path -> string creates a string of quotes files same as quote' (glob path) Util.wildcmp wildcard str -> bool The basic comparison function used for globbing - not optimized. Chomping: chomp suffix str -> string chomp ".ml" "hello.ml" -> "hello" prechomp prefix str -> string prechomp "hello" "hello.ml" -> ".ml" Shell execution: quote path -> string translate / to platform path separator then handle spaces and other symbols needing escape. Adds a single trailing space. quote' path_list -> string apply quote to all paths in list then concate the list to a string with a single trailing space. concat path path -> string concatenates to paths like concat "x" "y" -> "x/y" join sep xs -> string concatenate the string list xs by inserting the string sep between each element dirname path -> string dirname "x/y/z" -> "x/y", dirname "x" -> ".", dirname "/x" -> "/", dirname "." -> ".", dirname "/" -> "/" basename path -> string basename "x/y/z.ml" -> "z.ml", basename "x" -> "x" os_path mypath -> translates / to \ which is needed by some Windows shell commands. Does nothing on Unix. cd x -> () chdir x -> () change current working directory pwd () -> string print current working directory as an absolute path pushd x -> () push working directory on a stack, then change to the directory x popd () -> () or exception Not_found pop last directory from stack and change working directory, raise Not_found if stack is empty with unchanged working directory ls_d wildcard -> string list alias for glob wildcard, see globbing corresponds to unix 'ls -d' sh cmdstring -> () or exception execute a system command like sh "wget http://www.example.org/hello.html" sh' cmdstring_list -> () or exception join argument list to a space separated string then execute as a single command sh'' cmdstring_list_list -> () or exception for sublist in argument: join argument list to a space separated string then execute as a single command example: sh'' [["cat"; glob' "*.log"; "logs"]; ["tar"; "czf"; "logs"]] rp cmdstring -> string read_process cmdstring -> string execute a system command and return stdout in a string, for example: read_process "cat version.txt" rpl cmdstring -> string read_process_line cmdstring -> string execute a system command and return first line of stdout in a string rpl' cmdstring -> string list read_process_lines cmdstring -> string list execute a system command and return stdout in as a list of lines Environment accessor functions: platform -> string with on of the values "Windows", "Unix", "Cygwin" we translate Sys.os_type form Win32 to Windows because it is confusing on 64-bit Windows. Unix cover all supported variants, including OS-X. home () -> string Full path to user home directory is used to expand ~ in globbing, reads env "HOME" on Unix and "HOMEPATH" on Windows, it is a function since it could change. Fails with exception if home is defined as '~' to protect globbing logic. ocaml_libdir -> string Full path to ocaml library directory as defined by 'ocamlc -where' env name -> string or Not_found exception get the env variable with matching the name env_opt argnum missing_value -> string export name value -> () update the environment variable 'name; useful before calling external commands relying on variables like $LIBDIR arg arg_num -> string or Not_found exception get the commond line argument at the integer position argnum (arg 0) is the script name, (arg 1) is the first argument, if any. arg_opt arg_num missing_value -> string Make style arg processing: params -> (string * string) list of all arguments with the form 'name=value' param name -> string or Not_found exception find the first matching argument of the form 'name=value' and return the value param_opt name missing_value -> string get_default_permissions int -> int set_default_permissions int -> () The unix permissions, like 0o744, used when creating a directory or touching a file. KNOWN ISSUES: - OS-X permissions: it seems that trying to move a file into a read-only directory on OS-X will silently fail. The underlying Sys.rename function ought to raise an exception - this is not the same os platform specific silent overwrite. Running the same "mv" command in a shell results in an error.