# Module FileUtil

    module FileUtil: sig .. end

POSIX utilities for files and directories.

A module to provide the core POSIX utilities to manipulate files and directories. All function nearly match common POSIX utilities but in rewritten OCaml.
Author(s): Sylvain Le Gall

## Types and exceptions

    exception SizeInvalid

    exception FileDoesntExist of FilePath.filename

    exception RecursiveLink of FilePath.filename

    exception RmDirNotEmpty of FilePath.filename

    exception RmDirNoRecurse of FilePath.filename

    exception MkdirMissingComponentPath of FilePath.filename

    exception MkdirDirnameAlreadyUsed of FilePath.filename

    exception CpCannotCopy of FilePath.filename

    exception CpNoSourceFile of FilePath.filename

    exception CpCannotCopyFilesToFile of FilePath.filename list * FilePath.filename

    exception CpCannotCopyDir of FilePath.filename

    exception MvNoSourceFile

    type action_link =

`|` | `Follow` | `(*` | We consider link as simple directory (it is dangerous) | `*)`
`|` | `Skip` | `(*` | Just skip it | `*)`
`|` | `SkipInform of `(FilePath.filename -> unit)`` | `(*` | Skip and execute an action | `*)`
`|` | `AskFollow of `(FilePath.filename -> bool)`` | `(*` | Ask and wait for input, false means skip | `*)`

Policy concerning links which are directories

    type interactive =

`|` | `Force` | `(*` | Do it anyway | `*)`
`|` | `Ask of `(FilePath.filename -> bool)`` | `(*` | Promp the user | `*)`

For certain command, you should need to ask the user wether or not he wants to act.

    type size =

`|` | `TB of `int64`` | `(*` | Tera bytes | `*)`
`|` | `GB of `int64`` | `(*` | Giga bytes | `*)`
`|` | `MB of `int64`` | `(*` | Mega bytes | `*)`
`|` | `KB of `int64`` | `(*` | Kilo bytes | `*)`
`|` | `B of `int64`` | `(*` | Bytes | `*)`

File size

    type kind =

`|` | `Dir`
`|` | `File`
`|` | `Dev_char`
`|` | `Dev_block`
`|` | `Fifo`
`|` | `Socket`

Kind of file. This set is a combination of all POSIX file, some of them doesn't exist at all on certain file system or OS.

    type base_permission = {

`` | `sticky : `bool`;`
`` | `exec : `bool`;`
`` | `write : `bool`;`
`` | `read : `bool`;`

}
Base permission. This is the permission corresponding to one user or group.

    type permission = {

`` | `user : `base_permission`;`
`` | `group : `base_permission`;`
`` | `other : `base_permission`;`

}
Full permission. All the base permissions of a file.

    type stat = {

`` | `kind : `kind`;`
`` | `is_link : `bool`;`
`` | `permission : `permission`;`
`` | `size : `size`;`
`` | `owner : `int`;`
`` | `group_owner : `int`;`
`` | `access_time : `float`;`
`` | `modification_time : `float`;`
`` | `creation_time : `float`;`

}
Information about a file. This type is derived from Unix.stat

    type test_file =

`|` | `Is_dev_block` | `(*` | FILE is block special | `*)`
`|` | `Is_dev_char` | `(*` | FILE is character special | `*)`
`|` | `Is_dir` | `(*` | FILE is a directory | `*)`
`|` | `Exists` | `(*` | FILE exists | `*)`
`|` | `Is_file` | `(*` | FILE is a regular file | `*)`
`|` | `Is_set_group_ID` | `(*` | FILE is set-group-ID | `*)`
`|` | `Has_sticky_bit` | `(*` | FILE has its sticky bit set | `*)`
`|` | `Is_link` | `(*` | FILE is a symbolic link | `*)`
`|` | `Is_pipe` | `(*` | FILE is a named pipe | `*)`
`|` | `Is_readable` | `(*` | FILE is readable | `*)`
`|` | `Is_writeable` | `(*` | FILE is writeable | `*)`
`|` | `Size_not_null` | `(*` | FILE has a size greater than zero | `*)`
`|` | `Size_bigger_than of `size`` | `(*` | FILE has a size greater than given size | `*)`
`|` | `Size_smaller_than of `size`` | `(*` | FILE has a size smaller than given size | `*)`
`|` | `Size_equal_to of `size`` | `(*` | FILE has the same size as given size | `*)`
`|` | `Size_fuzzy_equal_to of `size`` | `(*` | FILE has approximatively the same size as given size | `*)`
`|` | `Is_socket` | `(*` | FILE is a socket | `*)`
`|` | `Has_set_user_ID` | `(*` | FILE its set-user-ID bit is set | `*)`
`|` | `Is_exec` | `(*` | FILE is executable | `*)`
`|` | `Is_owned_by_user_ID` | `(*` | FILE is owned by the effective user ID | `*)`
`|` | `Is_owned_by_group_ID` | `(*` | FILE is owned by the effective group ID | `*)`
`|` | `Is_newer_than of `FilePath.filename`` | `(*` | FILE1 is newer (modification date) than FILE2 | `*)`
`|` | `Is_older_than of `FilePath.filename`` | `(*` | FILE1 is older than FILE2 | `*)`
`|` | `Is_newer_than_date of `float`` | `(*` | FILE is newer than given date | `*)`
`|` | `Is_older_than_date of `float`` | `(*` | FILE is older than given date | `*)`
`|` | `And of `test_file * test_file`` | `(*` | Result of TEST1 and TEST2 | `*)`
`|` | `Or of `test_file * test_file`` | `(*` | Result of TEST1 or TEST2 | `*)`
`|` | `Not of `test_file`` | `(*` | Result of not TEST | `*)`
`|` | `Match of `string`` | `(*` | Compilable match (Str or PCRE or ...) | `*)`
`|` | `True` | `(*` | Always true | `*)`
`|` | `False` | `(*` | Always false | `*)`
`|` | `Has_extension of `FilePath.extension`` | `(*` | Check extension | `*)`
`|` | `Has_no_extension` | `(*` | Check absence of extension | `*)`
`|` | `Is_parent_dir` | `(*` | Basename is the parent dir | `*)`
`|` | `Is_current_dir` | `(*` | Basename is the current dir | `*)`
`|` | `Basename_is of `FilePath.filename`` | `(*` | Check the basename | `*)`
`|` | `Dirname_is of `FilePath.filename`` | `(*` | Check the dirname | `*)`
`|` | `Custom of `(FilePath.filename -> bool)`` | `(*` | Custom operation on filename | `*)`

Pattern you can use to test file. If the file doesn't exist the result is always false.

    type touch_time_t =

`|` | `Touch_now` | `(*` | Use Unix.gettimeofday | `*)`
`|` | `Touch_file_time of `FilePath.filename`` | `(*` | Get mtime of file | `*)`
`|` | `Touch_timestamp of `float`` | `(*` | Use GMT timestamp | `*)`

Time for file

## Classical permission

    val permission_of_int : int -> permission

Translate POSIX integer permission.

    val int_of_permission : permission -> int

Return the POSIX integer permission

## Size operation

    val byte_of_size : size -> int64

Convert size to bytes

    val size_add : size -> size -> size

Add two size

    val size_compare : ?fuzzy:bool -> size -> size -> int

Compare two size, using the classical compare function. If fuzzy is set to true, the comparison is done on the most significant size unit of both value.

    val string_of_size : ?fuzzy:bool -> size -> string

Convert a value to a string representation. If fuzzy is set to true, only consider the most significant unit

## Operations on files and directories

    val stat : FilePath.filename -> stat

`stat fln` Return information about the file (like Unix.stat)

    val test : ?match_compile:(FilePath.filename -> FilePath.filename -> bool) ->
           test_file -> FilePath.filename -> bool

Test a file

    val pwd : unit -> FilePath.filename

Return the currend dir

    val readlink : FilePath.filename -> SetFilename.elt

Resolve to the real filename removing symlink

    val ls : FilePath.filename -> FilePath.filename list

List the content of a directory

    val filter : test_file -> FilePath.filename list -> FilePath.filename list

Apply a filtering pattern to a filename

    val which : ?path:FilePath.filename list -> FilePath.filename -> FilePath.filename

Try to find the executable in the PATH. Use environement variable PATH if none is provided

    val mkdir : ?parent:bool -> ?mode:Unix.file_perm -> FilePath.filename -> unit

Create the directory which name is provided. Turn parent to true if you also want to create every topdir of the path. Use mode to provide some specific right (default 755).

    val touch : ?atime:bool ->
           ?mtime:bool ->
           ?create:bool -> ?time:touch_time_t -> FilePath.filename -> unit

Modify the timestamp of the given filename.
`atime` : modify access time, default true
`mtime` : modify modification time, default true
`create` : if file doesn't exist, create it, default true
`time` : what time to set, default Touch_now

    val find : ?follow:action_link ->
           ?match_compile:(FilePath.filename -> FilePath.filename -> bool) ->
           test_file ->
           FilePath.filename -> ('a -> FilePath.filename -> 'a) -> 'a -> 'a

`find ~follow:fol tst fln exec accu` Descend the directory tree starting from the given filename and using the test provided. You cannot match `current_dir` and `parent_dir`. For every file found, the action `exec` is done, using the `accu` to start. For a simple file listing, you can use `find True "." (fun x y -> y :: x) []`

    val rm : ?force:interactive ->
           ?recurse:bool -> FilePath.filename list -> unit

Remove the filename provided. Turn recurse to true in order to completely delete a directory

    val cp : ?follow:action_link ->
           ?force:interactive ->
           ?recurse:bool -> FilePath.filename list -> FilePath.filename -> unit

Copy the hierarchy of files/directory to another destination

    val mv : ?force:interactive -> FilePath.filename -> FilePath.filename -> unit

Move files/directories to another destination

    val cmp : ?skip1:int ->
           FilePath.filename -> ?skip2:int -> FilePath.filename -> int option

`cmp skip1 fln1 skip2 fln2` Compare files `fln1` and `fln2` starting at pos `skip1` `skip2` and returning the first octect where a difference occurs. Returns `Some -1` if one of the file is not readable or if it is not a file.

    val du : FilePath.filename list ->
           size * (FilePath.filename * size) list

`du fln_lst` Return the amount of space of all the file which are subdir of fln_lst. Also return details for each file scanned
For future release :

- `val pathchk: filename -> boolean * string`, check whether file names are valid or portable
- `val chmod: filename -> permission -> unit`, change file mode bits (only UNIX bit mask)
- `val setfacl: filename -> permission -> unit`, set file access control lists (UNIX + extended attribute)
- `val getfacl: filename -> permission`, get file access control lists

ACL related function will be handled through a plugin system to handle at runtime which attribute can be read/write (i.e. Win32 ACL, NFS acl, Linux ACL -- or none).