Determine the target of a symbolic link. This uses the readlink(2) system call. The result is a path which is either absolute, or relative to
the directory which the symlink is in. In case of an error, an IOError is thrown. The path is included and can be accessed with
IO.ioeGetFileName. Note that, if the path to the symlink ends with a slash, this path denotes the directory pointed to, not the symlink. In
this case the call to will fail because of "Invalid argument".

Determine the target of a symbolic link. This uses the readlink(2) system call. The target is converted, such that it is relative to the
current working directory, if it isn't absolute. Note that, if the path to the symlink ends with a slash, this path denotes the directory pointed
to, not the symlink. In this case the call to readlink will fail with an IOError because of "Invalid argument". In case of any error, a
proper IOError is thrown.

Return the normalised, absolute version of a specified path. The path is made absolute with the current working directory, and is syntactically
normalised afterwards. This is the same as what the realpath program reports with the -s option. It's almost the same as what it reports when
called from a shell. The difference lies in the shell's idea of the current working directory. See cd for details.

Make a symbolic link. This is the symlink(2) function. Any error results in an IOError thrown. The path of the intended symlink is included in
the IOError and
can be accessed with ioeGetFileName from the Haskell standard library IO.

Create directory. This is a shorthand to System.Directory.createDirectory from the Haskell standard
library. In case of an error, the path is included in the IOError, which GHC's implementation neglects to do.

Change directory. This is an alias for Directory.setCurrentDirectory from the Haskell standard
library. In case of an error, the path is included in the IOError, which GHC's implementation neglects to do.

Note that this command is subtly different from the shell's cd command. It changes the process' working directory. This is always a realpath.
Symlinks are expanded. The shell, on the other hand, keeps track of the current working directory separately, in a different way: symlinks are
not expanded. The shell's idea of the working directory is different from the working directory which a process has.

This means that the same sequence of cd commands, when done in a real shell script, will lead into the same directory. But the working directory
as reported by the shell's pwd command may differ from the corresponding one, reported by getCurrentDirectory.

(When talking about the "shell", I'm talking about bash, regardless of whether started as /bin/bash or in compatibility mode, as /bin/sh. I
presume it's the standard behavior for the POSIX standard shell.)

Get program start working directory. This is the PWD environent
variable, which is kept by the shell (bash, at least). It records the
directory path in which the program has been started. Symbolic links in
this path aren't expanded. In this way, it differs from
getCurrentDirectory from the Haskell standard library.

The rename(2) system call to rename and/or move a file. The renameFile action from the Haskell standard library doesn't do it, because
the two paths may not refer to directories. Failure results in an IOError thrown. The new path is included in
the IOError and
can be accessed with IO.ioeGetFileName.

Rename a file. This first tries rename, which is most efficient. If it fails, because source and target path point to different file systems
(as indicated by the errno value EXDEV), then /bin/mv is called.

This renames a file or directory, using rename, sets the necessary write permissions beforehand, and restores them afterwards. This is more
efficient than force_mv, because no external program needs to be called, but it can rename files only inside the same file system. See force_cmd
for a detailed description.

The new path may be an existing directory. In this case, it is assumed that the old file is to be moved into this directory (like with mv). The
new path is then completed with the file name component of the old path. You won't get an "already exists" error.

This moves a file or directory, using the external command mv, sets the necessary write permissions beforehand, and restores them afterwards.
This is less efficient than force_rename, because the external program mv needs to be called, but it can move files between file systems. See
force_cmd for a detailed description.

Rename a file with rename, or when necessary with mv, and cope with read only issues.

The necessary write permissions are set, then the file is renamed, then the permissions are restored.

First, the rename system call is tried, which is most efficient. If it fails, because source and target path point to different file systems
(as indicated by the errno value EXDEV), then /bin/mv is called.

force_rename_mv old new = fill_in_location "force_rename_mv" $ force_cmd rename_mv old new

Call a command which moves a file or directory, and cope with read only issues.

This function is for calling a command, which renames files. Beforehand, write permissions are set in order to enable the
operation, and afterwards the permissions are restored. The command is meant to be something like rename or run "/bin/mv".

In order to change the name of a file or dirctory, but leave it in the super directory
it is in, the super directory must be writeable. In order to move a file or directory to a different super directory, both super directories and
the file/directory to be moved must be writeable. I don't know what this behaviour is supposed to be good for.

This function copes with the case that the file/directory to be moved or renamed, or the super directories are read only. It makes the necessary
places writeable, calls the command, and makes them read only again, if they were before. The user needs the necessary permissions for changing the
corresponding write permissions. If an error occurs (such as file not found, or insufficient permissions), then the write permissions are restored
to the state before, before the exception is passed through to the caller.

The command must take two arguments, the old path and the new path. It is expected to create the new path in the file system, such that the correct
write permissions of the new path can be set by force_cmd after executing it.

The new path may be an existing directory. In this case, it is assumed that the old file is to be moved into this directory (like with mv). The
new path is completed with the file name component of the old path, before it is passed to the command, such that the command is supplied the
complete new path.

Examples:

force_cmd rename from to
force_cmd (\from to -> run "/bin/mv" ["-i", "-v", "--", from, to]) from to

Make a file or directory writeable for the user, perform an action, and restore its writeable status. An IOError is raised when the user doesn't
have permission to make the file or directory writeable.

Make a file or directory writeable for the user, perform an action, and restore its writeable status. The action may change the name of the file
or directory. Therefore it returns the new name, along with another return value, which is passed to the caller.

The writeable status is only changed back if it has been changed by force_writeable2 before. An IOError is raised when the user doesn'h have
permission to make the file or directory writeable, or when the new path doesn't exist.

For each set of identical files, and each of the specified directories, the paths of the identical files in this
directory.

Call the fdupes program in order to find identical files. It outputs a
list of groups of file names, such that the files in each group are
identical. Each of these groups is further analysed by the fdupes
action. It is split to a list of lists of paths, such that each list
of paths corresponds to one of the directories which have been searched
by the fdupes program. If you just want groups of identical files, then apply map concat to the result.

Thefdupes /program doesn't handle multiple occurences of the same directory, or in recursive mode one specified directory containing another,
properly. The same file may get reported multiple times, and identical files may not get reported./