# os

- Manual
- Standard library
- Index

Search:
Group by:

This module contains basic operating system facilities like retrieving environment variables, reading command line arguments, working with directories, running shell commands, etc.

    import os

    let myFile = "/path/to/my/file.nim"

    let splittedPath = splitPath(myFile)
    assert splittedPath.head == "/path/to/my"
    assert splittedPath.tail == "file.nim"

    assert parentDir(myFile) == "/path/to/my"

    let splittedFile = splitFile(myFile)
    assert splittedFile.dir == "/path/to/my"
    assert splittedFile.name == "file"
    assert splittedFile.ext == ".nim"

    assert myFile.changeFileExt("c") == "/path/to/my/file.c"

See also:

- osproc module for process communication beyond execShellCmd proc
- parseopt module for command-line parser beyond parseCmdLine proc
- uri module
- distros module
- dynlib module
- streams module

# Imports

strutils, pathnorm, winlean, times, winlean, parseutils

# Types

    ReadEnvEffect = object of ReadIOEffect

  Effect that denotes a read from an environment variable. Source Edit

    WriteEnvEffect = object of WriteIOEffect

  Effect that denotes a write to an environment variable. Source Edit

    ReadDirEffect = object of ReadIOEffect

  Effect that denotes a read operation from the directory structure. Source Edit

    WriteDirEffect = object of WriteIOEffect

  Effect that denotes a write operation to the directory structure. Source Edit

    OSErrorCode = distinct int32

  Specifies an OS Error Code. Source Edit

    FilePermission = enum
      fpUserExec,                 ## execute access for the file owner
      fpUserWrite,                ## write access for the file owner
      fpUserRead,                 ## read access for the file owner
      fpGroupExec,                ## execute access for the group
      fpGroupWrite,               ## write access for the group
      fpGroupRead,                ## read access for the group
      fpOthersExec,               ## execute access for others
      fpOthersWrite,              ## write access for others
      fpOthersRead                ## read access for others

  File access permission, modelled after UNIX.

  See also:

  - getFilePermissions
  - setFilePermissions
  - FileInfo object
  Source Edit

    PathComponent = enum
      pcFile,                     ## path refers to a file
      pcLinkToFile,               ## path refers to a symbolic link to a file
      pcDir,                      ## path refers to a directory
      pcLinkToDir                 ## path refers to a symbolic link to a directory

  Enumeration specifying a path component.

  See also:

  - walkDirRec iterator
  - FileInfo object
  Source Edit

    DeviceId = int32

  Source Edit

    FileId = int64

  Source Edit

    FileInfo = object
      id*: tuple[device: DeviceId, file: FileId] ## Device and file id.
      kind*: PathComponent         ## Kind of file object - directory, symlink, etc.
      size*: BiggestInt            ## Size of file.
      permissions*: set[FilePermission] ## File permissions
      linkCount*: BiggestInt       ## Number of hard links the file object has.
      lastAccessTime*: times.Time  ## Time file was last accessed.
      lastWriteTime*: times.Time   ## Time file was last modified/written to.
      creationTime*: times.Time    ## Time file was created. Not supported on all systems!

  Contains information associated with a file object.

  See also:

  - getFileInfo(handle) proc
  - getFileInfo(file) proc
  - getFileInfo(path) proc
  Source Edit

# Consts

    doslikeFileSystem = true

  Source Edit

    CurDir = '.'

  The constant character used by the operating system to refer to the current directory.

  For example: `'.'` for POSIX or `':'` for the classic Macintosh.

  Source Edit

    ParDir = ".."

  The constant string used by the operating system to refer to the parent directory.

  For example: `".."` for POSIX or `"::"` for the classic Macintosh.

  Source Edit

    DirSep = '/'

  The character used by the operating system to separate pathname components, for example: `'/'` for POSIX, `':'` for the classic Macintosh, and `'\'` on Windows. Source Edit

    AltSep = '/'

  An alternative character used by the operating system to separate pathname components, or the same as DirSep if only one separator character exists. This is set to `'/'` on Windows systems where DirSep is a backslash (`'\'`). Source Edit

    PathSep = ':'

  The character conventionally used by the operating system to separate search patch components (as in PATH), such as `':'` for POSIX or `';'` for Windows. Source Edit

    FileSystemCaseSensitive = true

  True if the file system is case sensitive, false otherwise. Used by cmpPaths proc to compare filenames properly. Source Edit

    ExeExt = ""

  The file extension of native executables. For example: `""` for POSIX, `"exe"` on Windows (without a dot). Source Edit

    ScriptExt = ""

  The file extension of a script file. For example: `""` for POSIX, `"bat"` on Windows. Source Edit

    DynlibFormat = "lib$1.so"

  The format string to turn a filename into a DLL file (also called shared object on some operating systems). Source Edit

    ExtSep = '.'

  The character which separates the base filename from the extension; for example, the `'.'` in `os.nim`. Source Edit

    ExeExts = ["exe", "cmd", "bat"]

  Platform specific file extension for executables. On Windows `["exe", "cmd", "bat"]`, on Posix `[""]`. Source Edit

# Procs

    proc joinPath(head, tail: string): string {...}{.noSideEffect, gcsafe, extern: "nos$1",
                                           raises: [], tags: [].}

  Joins two directory names to one.

  If `head` is the empty string, `tail` is returned. If `tail` is the empty string, `head` is returned with a trailing path separator. If `tail` starts with a path separator it will be removed when concatenated to `head`. Path separators will be normalized.

  See also:

  - joinPath(varargs) proc
  - / proc
  - splitPath proc
  - uri.combine proc
  - uri./ proc

  Examples:

      when defined(posix):
        assert joinPath("usr", "lib") == "usr/lib"
        assert joinPath("usr", "") == "usr/"
        assert joinPath("", "lib") == "lib"
        assert joinPath("", "/lib") == "/lib"
        assert joinPath("usr/", "/lib") == "usr/lib"
        assert joinPath("usr/lib", "../bin") == "usr/bin"

  Source Edit

    proc joinPath(parts: varargs[string]): string {...}{.noSideEffect, gcsafe,
        extern: "nos$1OpenArray", raises: [], tags: [].}

  The same as joinPath(head, tail) proc, but works with any number of directory parts.

  You need to pass at least one element or the proc will assert in debug builds and crash on release builds.

  See also:

  - joinPath(head, tail) proc
  - / proc
  - /../ proc
  - splitPath proc

  Examples:

      when defined(posix):
        assert joinPath("a") == "a"
        assert joinPath("a", "b", "c") == "a/b/c"
        assert joinPath("usr/lib", "../../var", "log") == "var/log"

  Source Edit

    proc `/`(head, tail: string): string {...}{.noSideEffect, raises: [], tags: [].}

  The same as joinPath(head, tail) proc.

  See also:

  - /../ proc
  - joinPath(head, tail) proc
  - joinPath(varargs) proc
  - splitPath proc
  - uri.combine proc
  - uri./ proc

  Examples:

      when defined(posix):
        assert "usr" / "" == "usr/"
        assert "" / "lib" == "lib"
        assert "" / "/lib" == "/lib"
        assert "usr/" / "/lib" == "usr/lib"
        assert "usr" / "lib" / "../bin" == "usr/bin"

  Source Edit

    proc splitPath(path: string): tuple[head, tail: string] {...}{.noSideEffect, gcsafe,
        extern: "nos$1", raises: [], tags: [].}

  Splits a directory into `(head, tail)` tuple, so that `head / tail == path` (except for edge cases like "/usr").

  See also:

  - joinPath(head, tail) proc
  - joinPath(varargs) proc
  - / proc
  - /../ proc
  - relativePath proc

  Examples:

      assert splitPath("usr/local/bin") == ("usr/local", "bin")
      assert splitPath("usr/local/bin/") == ("usr/local/bin", "")
      assert splitPath("bin") == ("", "bin")
      assert splitPath("/bin") == ("", "bin")
      assert splitPath("") == ("", "")

  Source Edit

    proc relativePath(path, base: string; sep = DirSep): string {...}{.noSideEffect, gcsafe,
        extern: "nos$1", raises: [], tags: [].}

  Converts `path` to a path relative to `base`.

  The `sep` (default: DirSep) is used for the path normalizations, this can be useful to ensure the relative path only contains `'/'` so that it can be used for URL constructions.

  See also:

  - splitPath proc
  - parentDir proc
  - tailDir proc

  Examples:

      assert relativePath("/Users/me/bar/z.nim", "/Users/other/bad", '/') ==
          "../../me/bar/z.nim"
      assert relativePath("/Users/me/bar/z.nim", "/Users/other", '/') ==
          "../me/bar/z.nim"
      assert relativePath("/Users///me/bar//z.nim", "//Users/", '/') == "me/bar/z.nim"
      assert relativePath("/Users/me/bar/z.nim", "/Users/me", '/') == "bar/z.nim"
      assert relativePath("", "/users/moo", '/') == ""

  Source Edit

    proc parentDir(path: string): string {...}{.noSideEffect, gcsafe, extern: "nos$1",
                                       raises: [], tags: [].}

  Returns the parent directory of `path`.

  This is the same as `splitPath(path).head` when `path` doesn't end in a dir separator. The remainder can be obtained with lastPathPart(path) proc.

  See also:

  - relativePath proc
  - splitPath proc
  - tailDir proc
  - parentDirs iterator

  Examples:

      assert parentDir("") == ""
      when defined(posix):
        assert parentDir("/usr/local/bin") == "/usr/local"
        assert parentDir("foo/bar/") == "foo"
        assert parentDir("foo/bar//") == "foo"
        assert parentDir("//foo//bar//") == "//foo"
        assert parentDir("./foo") == "."
        assert parentDir("/foo") == ""

  Source Edit

    proc tailDir(path: string): string {...}{.noSideEffect, gcsafe, extern: "nos$1", raises: [],
                                     tags: [].}

  Returns the tail part of `path`.

  See also:

  - relativePath proc
  - splitPath proc
  - parentDir proc

  Examples:

      assert tailDir("/bin") == "bin"
      assert tailDir("bin") == ""
      assert tailDir("bin/") == ""
      assert tailDir("/usr/local/bin") == "usr/local/bin"
      assert tailDir("//usr//local//bin//") == "usr//local//bin//"
      assert tailDir("./usr/local/bin") == "usr/local/bin"
      assert tailDir("usr/local/bin") == "local/bin"

  Source Edit

    proc isRootDir(path: string): bool {...}{.noSideEffect, gcsafe, extern: "nos$1", raises: [],
                                     tags: [].}

  Checks whether a given `path` is a root directory.

  Examples:

      assert isRootDir("")
      assert isRootDir(".")
      assert isRootDir("/")
      assert isRootDir("a")
      assert not isRootDir("/a")
      assert not isRootDir("a/b/c")

  Source Edit

    proc `/../`(head, tail: string): string {...}{.noSideEffect, raises: [], tags: [].}

  The same as `parentDir(head) / tail`, unless there is no parent directory. Then `head / tail` is performed instead.

  See also:

  - / proc
  - parentDir proc

  Examples:

      when defined(posix):
        assert "a/b/c" /../ "d/e" == "a/b/d/e"
        assert "a" /../ "d/e" == "a/d/e"

  Source Edit

    proc searchExtPos(path: string): int {...}{.raises: [], tags: [].}

  Returns index of the `'.'` char in `path` if it signifies the beginning of extension. Returns -1 otherwise.

  See also:

  - splitFile proc
  - extractFilename proc
  - lastPathPart proc
  - changeFileExt proc
  - addFileExt proc

  Examples:

      assert searchExtPos("a/b/c") == -1
      assert searchExtPos("c.nim") == 1
      assert searchExtPos("a/b/c.nim") == 5
      assert searchExtPos("a.b.c.nim") == 5

  Source Edit

    proc splitFile(path: string): tuple[dir, name, ext: string] {...}{.noSideEffect, gcsafe,
        extern: "nos$1", raises: [], tags: [].}

  Splits a filename into `(dir, name, extension)` tuple.

  `dir` does not end in DirSep. `extension` includes the leading dot.

  If `path` has no extension, `ext` is the empty string. If `path` has no directory component, `dir` is the empty string. If `path` has no filename component, `name` and `ext` are empty strings.

  See also:

  - searchExtPos proc
  - extractFilename proc
  - lastPathPart proc
  - changeFileExt proc
  - addFileExt proc

  Examples:

      var (dir, name, ext) = splitFile("usr/local/nimc.html")
      assert dir == "usr/local"
      assert name == "nimc"
      assert ext == ".html"
      (dir, name, ext) = splitFile("/usr/local/os")
      assert dir == "/usr/local"
      assert name == "os"
      assert ext == ""
      (dir, name, ext) = splitFile("/usr/local/")
      assert dir == "/usr/local"
      assert name == ""
      assert ext == ""

  Source Edit

    proc extractFilename(path: string): string {...}{.noSideEffect, gcsafe, extern: "nos$1",
        raises: [], tags: [].}

  Extracts the filename of a given `path`.

  This is the same as `name & ext` from splitFile(path) proc.

  See also:

  - searchExtPos proc
  - splitFile proc
  - lastPathPart proc
  - changeFileExt proc
  - addFileExt proc

  Examples:

      assert extractFilename("foo/bar/") == ""
      assert extractFilename("foo/bar") == "bar"
      assert extractFilename("foo/bar.baz") == "bar.baz"

  Source Edit

    proc lastPathPart(path: string): string {...}{.noSideEffect, gcsafe, extern: "nos$1",
                                          raises: [], tags: [].}

  Like extractFilename proc, but ignores trailing dir separator; aka: baseName in some other languages.

  See also:

  - searchExtPos proc
  - splitFile proc
  - extractFilename proc
  - changeFileExt proc
  - addFileExt proc

  Examples:

      assert lastPathPart("foo/bar/") == "bar"
      assert lastPathPart("foo/bar") == "bar"

  Source Edit

    proc changeFileExt(filename, ext: string): string {...}{.noSideEffect, gcsafe,
        extern: "nos$1", raises: [], tags: [].}

  Changes the file extension to `ext`.

  If the `filename` has no extension, `ext` will be added. If `ext` == "" then any extension is removed.

  `Ext` should be given without the leading `'.'`, because some filesystems may use a different character. (Although I know of none such beast.)

  See also:

  - searchExtPos proc
  - splitFile proc
  - extractFilename proc
  - lastPathPart proc
  - addFileExt proc

  Examples:

      assert changeFileExt("foo.bar", "baz") == "foo.baz"
      assert changeFileExt("foo.bar", "") == "foo"
      assert changeFileExt("foo", "baz") == "foo.baz"

  Source Edit

    proc addFileExt(filename, ext: string): string {...}{.noSideEffect, gcsafe, extern: "nos$1",
        raises: [], tags: [].}

  Adds the file extension `ext` to `filename`, unless `filename` already has an extension.

  `Ext` should be given without the leading `'.'`, because some filesystems may use a different character. (Although I know of none such beast.)

  See also:

  - searchExtPos proc
  - splitFile proc
  - extractFilename proc
  - lastPathPart proc
  - changeFileExt proc

  Examples:

      assert addFileExt("foo.bar", "baz") == "foo.bar"
      assert addFileExt("foo.bar", "") == "foo.bar"
      assert addFileExt("foo", "baz") == "foo.baz"

  Source Edit

    proc cmpPaths(pathA, pathB: string): int {...}{.noSideEffect, gcsafe, extern: "nos$1",
                                          raises: [], tags: [].}

  Compares two paths.

  On a case-sensitive filesystem this is done case-sensitively otherwise case-insensitively. Returns:

  0 iff pathA == pathB
  < 0 iff pathA < pathB
  > 0 iff pathA > pathB

  Examples:

      when defined(macosx):
        assert cmpPaths("foo", "Foo") == 0
      elif defined(posix):
        assert cmpPaths("foo", "Foo") > 0

  Source Edit

    proc isAbsolute(path: string): bool {...}{.gcsafe, noSideEffect, extern: "nos$1", raises: [],
                                      tags: [].}

  Checks whether a given `path` is absolute.

  On Windows, network paths are considered absolute too.

  Examples:

      assert not "".isAbsolute
      assert not ".".isAbsolute
      when defined(posix):
        assert "/".isAbsolute
        assert not "a/".isAbsolute
        assert "/a/".isAbsolute

  Source Edit

    proc unixToNativePath(path: string; drive = ""): string {...}{.noSideEffect, gcsafe,
        extern: "nos$1", raises: [], tags: [].}

  Converts an UNIX-like path to a native one.

  On an UNIX system this does nothing. Else it converts `'/'`, `'.'`, `'..'` to the appropriate things.

  On systems with a concept of "drives", `drive` is used to determine which drive label to use during absolute path conversion. `drive` defaults to the drive of the current working directory, and is ignored on systems that do not have a concept of "drives".

  Source Edit

    proc `==`(err1, err2: OSErrorCode): bool {...}{.borrow.}

  Source Edit

    proc `$`(err: OSErrorCode): string {...}{.borrow.}

  Source Edit

    proc osErrorMsg(errorCode: OSErrorCode): string {...}{.raises: [], tags: [].}

  Converts an OS error code into a human readable string.

  The error code can be retrieved using the osLastError proc.

  If conversion fails, or `errorCode` is `0` then `""` will be returned.

  On Windows, the `-d:useWinAnsi` compilation flag can be used to make this procedure use the non-unicode Win API calls to retrieve the message.

  See also:

  - raiseOSError proc
  - osLastError proc

  Examples:

      when defined(linux):
        assert osErrorMsg(OSErrorCode(0)) == ""
        assert osErrorMsg(OSErrorCode(1)) == "Operation not permitted"
        assert osErrorMsg(OSErrorCode(2)) == "No such file or directory"

  Source Edit

    proc newOSError(errorCode: OSErrorCode; additionalInfo = ""): owned(ref OSError) {...}{.
        noinline, raises: [], tags: [].}

  Creates a new OSError exception.

  The `errorCode` will determine the message, osErrorMsg proc will be used to get this message.

  The error code can be retrieved using the osLastError proc.

  If the error code is `0` or an error message could not be retrieved, the message `unknown OS error` will be used.

  See also:

  - osErrorMsg proc
  - osLastError proc
  Source Edit

    proc raiseOSError(errorCode: OSErrorCode; additionalInfo = "") {...}{.noinline,
        raises: [OSError], tags: [].}

  Raises an OSError exception.

  Read the description of the newOSError proc to learn how the exception object is created.

  Source Edit

    proc osLastError(): OSErrorCode {...}{.sideEffect, raises: [], tags: [].}

  Retrieves the last operating system error code.

  This procedure is useful in the event when an OS call fails. In that case this procedure will return the error code describing the reason why the OS call failed. The `OSErrorMsg` procedure can then be used to convert this code into a string.

  Warning: The behaviour of this procedure varies between Windows and POSIX systems. On Windows some OS calls can reset the error code to `0` causing this procedure to return `0`. It is therefore advised to call this procedure immediately after an OS call fails. On POSIX systems this is not a problem.

  See also:

  - osErrorMsg proc
  - raiseOSError proc
  Source Edit

    proc getEnv(key: string; default = ""): TaintedString {...}{.tags: [ReadEnvEffect], raises: [].}

  Returns the value of the environment variable named `key`.

  If the variable does not exist, `""` is returned. To distinguish whether a variable exists or it's value is just `""`, call existsEnv(key) proc.

  See also:

  - existsEnv proc
  - putEnv proc
  - envPairs iterator

  Examples:

      assert getEnv("unknownEnv") == ""
      assert getEnv("unknownEnv", "doesn\'t exist") == "doesn\'t exist"

  Source Edit

    proc existsEnv(key: string): bool {...}{.tags: [ReadEnvEffect], raises: [].}

  Checks whether the environment variable named `key` exists. Returns true if it exists, false otherwise.

  See also:

  - getEnv proc
  - putEnv proc
  - envPairs iterator

  Examples:

      assert not existsEnv("unknownEnv")

  Source Edit

    proc putEnv(key, val: string) {...}{.tags: [WriteEnvEffect], raises: [OSError].}

  Sets the value of the environment variable named `key` to `val`. If an error occurs, `OSError` is raised.

  See also:

  - getEnv proc
  - existsEnv proc
  - envPairs iterator
  Source Edit

    proc getHomeDir(): string {...}{.gcsafe, extern: "nos$1",
                             tags: [ReadEnvEffect, ReadIOEffect], raises: [].}

  Returns the home directory of the current user.

  This proc is wrapped by the expandTilde proc for the convenience of processing paths coming from user configuration files.

  See also:

  - getConfigDir proc
  - getTempDir proc
  - expandTilde proc
  - getCurrentDir proc
  - setCurrentDir proc

  Examples:

      assert getHomeDir() == expandTilde("~")

  Source Edit

    proc getConfigDir(): string {...}{.gcsafe, extern: "nos$1",
                               tags: [ReadEnvEffect, ReadIOEffect], raises: [].}

  Returns the config directory of the current user for applications.

  On non-Windows OSs, this proc conforms to the XDG Base Directory spec. Thus, this proc returns the value of the `XDG_CONFIG_HOME` environment variable if it is set, otherwise it returns the default configuration directory ("~/.config/").

  An OS-dependent trailing slash is always present at the end of the returned string: `\` on Windows and `/` on all other OSs.

  See also:

  - getHomeDir proc
  - getTempDir proc
  - expandTilde proc
  - getCurrentDir proc
  - setCurrentDir proc
  Source Edit

    proc getTempDir(): string {...}{.gcsafe, extern: "nos$1",
                             tags: [ReadEnvEffect, ReadIOEffect], raises: [].}

  Returns the temporary directory of the current user for applications to save temporary files in.

  Please do not use this: On Android, it currently returns `getHomeDir()`, and on other Unix based systems it can cause security problems too. That said, you can override this implementation by adding `-d:tempDir=mytempname` to your compiler invokation.

  See also:

  - getHomeDir proc
  - getConfigDir proc
  - expandTilde proc
  - getCurrentDir proc
  - setCurrentDir proc
  Source Edit

    proc expandTilde(path: string): string {...}{.tags: [ReadEnvEffect, ReadIOEffect],
                                         raises: [].}

  Expands `~` or a path starting with `~/` to a full path, replacing `~` with getHomeDir() (otherwise returns `path` unmodified).

  Windows: this is still supported despite Windows platform not having this convention; also, both `~/` and `~\` are handled.

  See also:

  - getHomeDir proc
  - getConfigDir proc
  - getTempDir proc
  - getCurrentDir proc
  - setCurrentDir proc

  Examples:

      assert expandTilde("~" / "appname.cfg") == getHomeDir() / "appname.cfg"
      assert expandTilde("~/foo/bar") == getHomeDir() / "foo/bar"
      assert expandTilde("/foo/bar") == "/foo/bar"

  Source Edit

    proc quoteShellWindows(s: string): string {...}{.noSideEffect, gcsafe, extern: "nosp$1",
                                            raises: [], tags: [].}

  Quote `s`, so it can be safely passed to Windows API.

  Based on Python's `subprocess.list2cmdline`. See this link for more details.

  Source Edit

    proc quoteShellPosix(s: string): string {...}{.noSideEffect, gcsafe, extern: "nosp$1",
                                          raises: [], tags: [].}

  Quote `s`, so it can be safely passed to POSIX shell. Based on Python's `pipes.quote`. Source Edit

    proc quoteShell(s: string): string {...}{.noSideEffect, gcsafe, extern: "nosp$1", raises: [],
                                     tags: [].}

  Quote `s`, so it can be safely passed to shell.

  When on Windows, it calls quoteShellWindows proc. Otherwise, calls quoteShellPosix proc.

  Source Edit

    proc quoteShellCommand(args: openArray[string]): string {...}{.raises: [], tags: [].}

  Concatenates and quotes shell arguments `args`.

  Examples:

      when defined(posix):
        assert quoteShellCommand(["aaa", "", "c d"]) == "aaa \'\' \'c d\'"
      when defined(windows):
        assert quoteShellCommand(["aaa", "", "c d"]) == "aaa \"\" \"c d\""

  Source Edit

    proc existsFile(filename: string): bool {...}{.gcsafe, extern: "nos$1",
                                          tags: [ReadDirEffect], raises: [].}

  Returns true if `filename` exists and is a regular file or symlink.

  Directories, device files, named pipes and sockets return false.

  See also:

  - existsDir proc
  - symlinkExists proc
  Source Edit

    proc existsDir(dir: string): bool {...}{.gcsafe, extern: "nos$1", tags: [ReadDirEffect],
                                    raises: [].}

  Returns true iff the directory `dir` exists. If `dir` is a file, false is returned. Follows symlinks.

  See also:

  - existsFile proc
  - symlinkExists proc
  Source Edit

    proc symlinkExists(link: string): bool {...}{.gcsafe, extern: "nos$1",
                                         tags: [ReadDirEffect], raises: [].}

  Returns true iff the symlink `link` exists. Will return true regardless of whether the link points to a directory or file.

  See also:

  - existsFile proc
  - existsDir proc
  Source Edit

    proc fileExists(filename: string): bool {...}{.inline, raises: [], tags: [ReadDirEffect].}

  Alias for existsFile proc.

  See also:

  - existsDir proc
  - symlinkExists proc
  Source Edit

    proc dirExists(dir: string): bool {...}{.inline, raises: [], tags: [ReadDirEffect].}

  Alias for existsDir proc.

  See also:

  - existsFile proc
  - symlinkExists proc
  Source Edit

    proc findExe(exe: string; followSymlinks: bool = true;
                extensions: openArray[string] = ExeExts): string {...}{.
        tags: [ReadDirEffect, ReadEnvEffect, ReadIOEffect], raises: [].}

  Searches for `exe` in the current working directory and then in directories listed in the `PATH` environment variable.

  Returns `""` if the `exe` cannot be found. `exe` is added the ExeExts file extensions if it has none.

  If the system supports symlinks it also resolves them until it meets the actual file. This behavior can be disabled if desired by setting `followSymlinks = false`.

  Source Edit

    proc getLastModificationTime(file: string): times.Time {...}{.gcsafe, extern: "nos$1",
        raises: [OSError], tags: [].}

  Returns the `file`'s last modification time.

  See also:

  - getLastAccessTime proc
  - getCreationTime proc
  - fileNewer proc
  Source Edit

    proc getLastAccessTime(file: string): times.Time {...}{.gcsafe, extern: "nos$1",
        raises: [OSError], tags: [].}

  Returns the `file`'s last read or write access time.

  See also:

  - getLastModificationTime proc
  - getCreationTime proc
  - fileNewer proc
  Source Edit

    proc getCreationTime(file: string): times.Time {...}{.gcsafe, extern: "nos$1",
        raises: [OSError], tags: [].}

  Returns the `file`'s creation time.

  Note: Under POSIX OS's, the returned time may actually be the time at which the file's attribute's were last modified. See here for details.

  See also:

  - getLastModificationTime proc
  - getLastAccessTime proc
  - fileNewer proc
  Source Edit

    proc fileNewer(a, b: string): bool {...}{.gcsafe, extern: "nos$1", raises: [OSError], tags: [].}

  Returns true if the file `a` is newer than file `b`, i.e. if `a`'s modification time is later than `b`'s.

  See also:

  - getLastModificationTime proc
  - getLastAccessTime proc
  - getCreationTime proc
  Source Edit

    proc getCurrentDir(): string {...}{.gcsafe, extern: "nos$1", tags: [], raises: [OSError].}

  Returns the current working directory.

  See also:

  - getHomeDir proc
  - getConfigDir proc
  - getTempDir proc
  - setCurrentDir proc
  Source Edit

    proc setCurrentDir(newDir: string) {...}{.inline, tags: [], raises: [OSError].}

  Sets the current working directory; `OSError` is raised if `newDir` cannot been set.

  See also:

  - getHomeDir proc
  - getConfigDir proc
  - getTempDir proc
  - getCurrentDir proc
  Source Edit

    proc absolutePath(path: string; root = getCurrentDir()): string {...}{.raises: [ValueError],
        tags: [].}

  Returns the absolute path of `path`, rooted at `root` (which must be absolute; default: current directory). If `path` is absolute, return it, ignoring `root`.

  See also:

  - normalizedPath proc
  - normalizePath proc

  Examples:

      assert absolutePath("a") == getCurrentDir() / "a"

  Source Edit

    proc normalizePath(path: var string) {...}{.gcsafe, extern: "nos$1", tags: [], raises: [].}

  Normalize a path.

  Consecutive directory separators are collapsed, including an initial double slash.

  On relative paths, double dot (`..`) sequences are collapsed if possible. On absolute paths they are always collapsed.

  Warning: URL-encoded and Unicode attempts at directory traversal are not detected. Triple dot is not handled.

  See also:

  - absolutePath proc
  - normalizedPath proc for a version which returns a new string

  Examples:

      when defined(posix):
        var a = "a///b//..//c///d"
        a.normalizePath()
        assert a == "a/c/d"

  Source Edit

    proc normalizedPath(path: string): string {...}{.gcsafe, extern: "nos$1", tags: [], raises: [].}

  Returns a normalized path for the current OS.

  See also:

  - absolutePath proc
  - normalizePath proc for the in-place version

  Examples:

      when defined(posix):
        assert normalizedPath("a///b//..//c///d") == "a/c/d"

  Source Edit

    proc sameFile(path1, path2: string): bool {...}{.gcsafe, extern: "nos$1",
                                           tags: [ReadDirEffect], raises: [OSError].}

  Returns true if both pathname arguments refer to the same physical file or directory.

  Raises `OSError` if any of the files does not exist or information about it can not be obtained.

  This proc will return true if given two alternative hard-linked or sym-linked paths to the same file or directory.

  See also:

  - sameFileContent proc
  Source Edit

    proc sameFileContent(path1, path2: string): bool {...}{.gcsafe, extern: "nos$1",
        tags: [ReadIOEffect], raises: [IOError].}

  Returns true if both pathname arguments refer to files with identical binary content.

  See also:

  - sameFile proc
  Source Edit

    proc getFilePermissions(filename: string): set[FilePermission] {...}{.gcsafe,
        extern: "nos$1", tags: [ReadDirEffect], raises: [OSError].}

  Retrieves file permissions for `filename`.

  `OSError` is raised in case of an error. On Windows, only the `readonly` flag is checked, every other permission is available in any case.

  See also:

  - setFilePermissions proc
  - FilePermission enum
  Source Edit

    proc setFilePermissions(filename: string; permissions: set[FilePermission]) {...}{.gcsafe,
        extern: "nos$1", tags: [WriteDirEffect], raises: [OSError].}

  Sets the file permissions for `filename`.

  `OSError` is raised in case of an error. On Windows, only the `readonly` flag is changed, depending on `fpUserWrite` permission.

  See also:

  - getFilePermissions
  - FilePermission enum
  Source Edit

    proc copyFile(source, dest: string) {...}{.gcsafe, extern: "nos$1",
                                      tags: [ReadIOEffect, WriteIOEffect],
                                      raises: [OSError].}

  Copies a file from `source` to `dest`.

  If this fails, `OSError` is raised.

  On the Windows platform this proc will copy the source file's attributes into dest.

  On other platforms you need to use getFilePermissions and setFilePermissions procs to copy them by hand (or use the convenience copyFileWithPermissions proc), otherwise `dest` will inherit the default permissions of a newly created file for the user.

  If `dest` already exists, the file attributes will be preserved and the content overwritten.

  See also:

  - copyDir proc
  - copyFileWithPermissions proc
  - tryRemoveFile proc
  - removeFile proc
  - moveFile proc
  Source Edit

    proc tryRemoveFile(file: string): bool {...}{.gcsafe, extern: "nos$1",
                                         tags: [WriteDirEffect], raises: [].}

  Removes the `file`.

  If this fails, returns `false`. This does not fail if the file never existed in the first place.

  On Windows, ignores the read-only attribute.

  See also:

  - copyFile proc
  - copyFileWithPermissions proc
  - removeFile proc
  - moveFile proc
  Source Edit

    proc removeFile(file: string) {...}{.gcsafe, extern: "nos$1", tags: [WriteDirEffect],
                                 raises: [OSError].}

  Removes the `file`.

  If this fails, `OSError` is raised. This does not fail if the file never existed in the first place.

  On Windows, ignores the read-only attribute.

  See also:

  - removeDir proc
  - copyFile proc
  - copyFileWithPermissions proc
  - tryRemoveFile proc
  - moveFile proc
  Source Edit

    proc moveFile(source, dest: string) {...}{.gcsafe, extern: "nos$1",
                                      tags: [ReadIOEffect, WriteIOEffect],
                                      raises: [OSError].}

  Moves a file from `source` to `dest`.

  If this fails, `OSError` is raised. If `dest` already exists, it will be overwritten.

  Can be used to rename files.

  See also:

  - moveDir proc
  - copyFile proc
  - copyFileWithPermissions proc
  - removeFile proc
  - tryRemoveFile proc
  Source Edit

    proc exitStatusLikeShell(status: cint): cint {...}{.raises: [], tags: [].}

  Converts exit code from `c_system` into a shell exit code. Source Edit

    proc execShellCmd(command: string): int {...}{.gcsafe, extern: "nos$1",
                                          tags: [ExecIOEffect], raises: [].}

  Executes a shell command.

  Command has the form 'program args' where args are the command line arguments given to program. The proc returns the error code of the shell when it has finished (zero if there is no error). The proc does not return until the process has finished.

  To execute a program without having a shell involved, use osproc.execProcess proc.

  Examples:

      discard execShellCmd("ls -la")

  Source Edit

    proc expandFilename(filename: string): string {...}{.gcsafe, extern: "nos$1",
        tags: [ReadDirEffect], raises: [OSError].}

  Returns the full (absolute) path of an existing file `filename`.

  Raises `OSError` in case of an error. Follows symlinks.

  Source Edit

    proc getCurrentCompilerExe(): string {...}{.compileTime, raises: [], tags: [].}

  This is getAppFilename() at compile time.

  Can be used to retrive the currently executing Nim compiler from a Nim or nimscript program, or the nimble binary inside a nimble program (likewise with other binaries built from compiler API).

  Source Edit

    proc removeDir(dir: string) {...}{.gcsafe, extern: "nos$1",
                               tags: [WriteDirEffect, ReadDirEffect], gcsafe, locks: 0,
                               raises: [OSError].}

  Removes the directory `dir` including all subdirectories and files in `dir` (recursively).

  If this fails, `OSError` is raised. This does not fail if the directory never existed in the first place.

  See also:

  - tryRemoveFile proc
  - removeFile proc
  - existsOrCreateDir proc
  - createDir proc
  - copyDir proc
  - copyDirWithPermissions proc
  - moveDir proc
  Source Edit

    proc existsOrCreateDir(dir: string): bool {...}{.gcsafe, extern: "nos$1",
                                            tags: [WriteDirEffect, ReadDirEffect],
                                            raises: [OSError, IOError].}

  Check if a directory `dir` exists, and create it otherwise.

  Does not create parent directories (fails if parent does not exist). Returns `true` if the directory already exists, and `false` otherwise.

  See also:

  - removeDir proc
  - createDir proc
  - copyDir proc
  - copyDirWithPermissions proc
  - moveDir proc
  Source Edit

    proc createDir(dir: string) {...}{.gcsafe, extern: "nos$1",
                               tags: [WriteDirEffect, ReadDirEffect],
                               raises: [OSError, IOError].}

  Creates the directory `dir`.

  The directory may contain several subdirectories that do not exist yet. The full path is created. If this fails, `OSError` is raised.

  It does not fail if the directory already exists because for most usages this does not indicate an error.

  See also:

  - removeDir proc
  - existsOrCreateDir proc
  - copyDir proc
  - copyDirWithPermissions proc
  - moveDir proc
  Source Edit

    proc copyDir(source, dest: string) {...}{.gcsafe, extern: "nos$1",
                                     tags: [WriteIOEffect, ReadIOEffect], gcsafe,
                                     locks: 0, raises: [OSError, IOError].}

  Copies a directory from `source` to `dest`.

  If this fails, `OSError` is raised.

  On the Windows platform this proc will copy the attributes from `source` into `dest`.

  On other platforms created files and directories will inherit the default permissions of a newly created file/directory for the user. Use copyDirWithPermissions proc to preserve attributes recursively on these platforms.

  See also:

  - copyDirWithPermissions proc
  - copyFile proc
  - copyFileWithPermissions proc
  - removeDir proc
  - existsOrCreateDir proc
  - createDir proc
  - moveDir proc
  Source Edit

    proc moveDir(source, dest: string) {...}{.tags: [ReadIOEffect, WriteIOEffect],
                                     raises: [OSError].}

  Moves a directory from `source` to `dest`.

  If this fails, `OSError` is raised.

  See also:

  - moveFile proc
  - copyDir proc
  - copyDirWithPermissions proc
  - removeDir proc
  - existsOrCreateDir proc
  - createDir proc
  Source Edit

    proc createSymlink(src, dest: string) {...}{.raises: [OSError], tags: [ReadDirEffect].}

  Create a symbolic link at `dest` which points to the item specified by `src`. On most operating systems, will fail if a link already exists.

  Warning: Some OS's (such as Microsoft Windows) restrict the creation of symlinks to root users (administrators).

  See also:

  - createHardlink proc
  - expandSymlink proc
  Source Edit

    proc createHardlink(src, dest: string) {...}{.raises: [OSError], tags: [].}

  Create a hard link at `dest` which points to the item specified by `src`.

  Warning: Some OS's restrict the creation of hard links to root users (administrators).

  See also:

  - createSymlink proc
  Source Edit

    proc copyFileWithPermissions(source, dest: string; ignorePermissionErrors = true) {...}{.
        raises: [OSError], tags: [ReadIOEffect, WriteIOEffect].}

  Copies a file from `source` to `dest` preserving file permissions.

  This is a wrapper proc around copyFile, getFilePermissions and setFilePermissions procs on non-Windows platforms.

  On Windows this proc is just a wrapper for copyFile proc since that proc already copies attributes.

  On non-Windows systems permissions are copied after the file itself has been copied, which won't happen atomically and could lead to a race condition. If `ignorePermissionErrors` is true (default), errors while reading/setting file attributes will be ignored, otherwise will raise `OSError`.

  See also:

  - copyFile proc
  - copyDir proc
  - tryRemoveFile proc
  - removeFile proc
  - moveFile proc
  - copyDirWithPermissions proc
  Source Edit

    proc copyDirWithPermissions(source, dest: string; ignorePermissionErrors = true) {...}{.
        gcsafe, extern: "nos$1", tags: [WriteIOEffect, ReadIOEffect], gcsafe, locks: 0,
        raises: [OSError, IOError].}

  Copies a directory from `source` to `dest` preserving file permissions.

  If this fails, `OSError` is raised. This is a wrapper proc around copyDir and copyFileWithPermissions procs on non-Windows platforms.

  On Windows this proc is just a wrapper for copyDir proc since that proc already copies attributes.

  On non-Windows systems permissions are copied after the file or directory itself has been copied, which won't happen atomically and could lead to a race condition. If `ignorePermissionErrors` is true (default), errors while reading/setting file attributes will be ignored, otherwise will raise `OSError`.

  See also:

  - copyDir proc
  - copyFile proc
  - copyFileWithPermissions proc
  - removeDir proc
  - moveDir proc
  - existsOrCreateDir proc
  - createDir proc
  Source Edit

    proc inclFilePermissions(filename: string; permissions: set[FilePermission]) {...}{.
        gcsafe, extern: "nos$1", tags: [ReadDirEffect, WriteDirEffect], raises: [OSError].}

  A convenience proc for:

      setFilePermissions(filename, getFilePermissions(filename)+permissions)

  Source Edit

    proc exclFilePermissions(filename: string; permissions: set[FilePermission]) {...}{.
        gcsafe, extern: "nos$1", tags: [ReadDirEffect, WriteDirEffect], raises: [OSError].}

  A convenience proc for:

      setFilePermissions(filename, getFilePermissions(filename)-permissions)

  Source Edit

    proc expandSymlink(symlinkPath: string): string {...}{.raises: [], tags: [].}

  Returns a string representing the path to which the symbolic link points.

  On Windows this is a noop, `symlinkPath` is simply returned.

  See also:

  - createSymlink proc
  Source Edit

    proc parseCmdLine(c: string): seq[string] {...}{.noSideEffect, gcsafe, extern: "nos$1",
                                            raises: [], tags: [].}

  Splits a command line into several components.

  Note: This proc is only occasionally useful, better use the parseopt module.

  On Windows, it uses the following parsing rules:

  - Arguments are delimited by white space, which is either a space or a tab.
  - The caret character (^) is not recognized as an escape character or delimiter. The character is handled completely by the command-line parser in the operating system before being passed to the argv array in the program.
  - A string surrounded by double quotation marks ("string") is interpreted as a single argument, regardless of white space contained within. A quoted string can be embedded in an argument.
  - A double quotation mark preceded by a backslash (") is interpreted as a literal double quotation mark character (").
  - Backslashes are interpreted literally, unless they immediately precede a double quotation mark.
  - If an even number of backslashes is followed by a double quotation mark, one backslash is placed in the argv array for every pair of backslashes, and the double quotation mark is interpreted as a string delimiter.
  - If an odd number of backslashes is followed by a double quotation mark, one backslash is placed in the argv array for every pair of backslashes, and the double quotation mark is "escaped" by the remaining backslash, causing a literal double quotation mark (") to be placed in argv.

  On Posix systems, it uses the following parsing rules: Components are separated by whitespace unless the whitespace occurs within `"` or `'` quotes.

  See also:

  - parseopt module
  - paramCount proc
  - paramStr proc
  - commandLineParams proc
  Source Edit

    proc paramCount(): int {...}{.tags: [ReadIOEffect], raises: [].}

  Returns the number of command line arguments given to the application.

  Unlike argc in C, if your binary was called without parameters this will return zero. You can query each individual paramater with paramStr proc or retrieve all of them in one go with commandLineParams proc.

  Availability: When generating a dynamic library (see `--app:lib`) on Posix this proc is not defined. Test for availability using declared().

  See also:

  - parseopt module
  - parseCmdLine proc
  - paramStr proc
  - commandLineParams proc

  Examples:

      when declared(paramCount):
        # Use paramCount() here
      else:
        # Do something else!

  Source Edit

    proc paramStr(i: int): TaintedString {...}{.tags: [ReadIOEffect], raises: [].}

  Returns the `i`-th command line argument given to the application.

  `i` should be in the range `1..paramCount()`, the `IndexError` exception will be raised for invalid values. Instead of iterating over paramCount() with this proc you can call the convenience commandLineParams().

  Similarly to argv in C, it is possible to call `paramStr(0)` but this will return OS specific contents (usually the name of the invoked executable). You should avoid this and call getAppFilename() instead.

  Availability: When generating a dynamic library (see `--app:lib`) on Posix this proc is not defined. Test for availability using declared().

  See also:

  - parseopt module
  - parseCmdLine proc
  - paramCount proc
  - commandLineParams proc
  - getAppFilename proc

  Examples:

      when declared(paramStr):
        # Use paramStr() here
      else:
        # Do something else!

  Source Edit

    proc commandLineParams(): seq[TaintedString] {...}{.raises: [], tags: [ReadIOEffect].}

  Convenience proc which returns the command line parameters.

  This returns only the parameters. If you want to get the application executable filename, call getAppFilename().

  Availability: On Posix there is no portable way to get the command line from a DLL and thus the proc isn't defined in this environment. You can test for its availability with declared().

  See also:

  - parseopt module
  - parseCmdLine proc
  - paramCount proc
  - paramStr proc
  - getAppFilename proc

  Examples:

      when declared(commandLineParams):
        # Use commandLineParams() here
      else:
        # Do something else!

  Source Edit

    proc getAppFilename(): string {...}{.gcsafe, extern: "nos$1", tags: [ReadIOEffect],
                                 raises: [].}

  Returns the filename of the application's executable. This proc will resolve symlinks.

  See also:

  - getAppDir proc
  - getCurrentCompilerExe proc
  Source Edit

    proc getAppDir(): string {...}{.gcsafe, extern: "nos$1", tags: [ReadIOEffect], raises: [].}

  Returns the directory of the application's executable.

  See also:

  - getAppFilename proc
  Source Edit

    proc sleep(milsecs: int) {...}{.gcsafe, extern: "nos$1", tags: [TimeEffect], raises: [].}

  Sleeps `milsecs` milliseconds. Source Edit

    proc getFileSize(file: string): BiggestInt {...}{.gcsafe, extern: "nos$1",
        tags: [ReadIOEffect], raises: [OSError].}

  Returns the file size of `file` (in bytes). `OSError` is raised in case of an error. Source Edit

    proc getFileInfo(handle: FileHandle): FileInfo {...}{.raises: [OSError], tags: [].}

  Retrieves file information for the file object represented by the given handle.

  If the information cannot be retrieved, such as when the file handle is invalid, `OSError` is raised.

  See also:

  - getFileInfo(file) proc
  - getFileInfo(path) proc
  Source Edit

    proc getFileInfo(file: File): FileInfo {...}{.raises: [IOError, OSError], tags: [].}

  Retrieves file information for the file object.

  See also:

  - getFileInfo(handle) proc
  - getFileInfo(path) proc
  Source Edit

    proc getFileInfo(path: string; followSymlink = true): FileInfo {...}{.raises: [OSError],
        tags: [].}

  Retrieves file information for the file object pointed to by `path`.

  Due to intrinsic differences between operating systems, the information contained by the returned FileInfo object will be slightly different across platforms, and in some cases, incomplete or inaccurate.

  When `followSymlink` is true (default), symlinks are followed and the information retrieved is information related to the symlink's target. Otherwise, information on the symlink itself is retrieved.

  If the information cannot be retrieved, such as when the path doesn't exist, or when permission restrictions prevent the program from retrieving file information, `OSError` is raised.

  See also:

  - getFileInfo(handle) proc
  - getFileInfo(file) proc
  Source Edit

    proc isHidden(path: string): bool {...}{.raises: [], tags: [].}

  Determines whether `path` is hidden or not, using this reference.

  On Windows: returns true if it exists and its "hidden" attribute is set.

  On posix: returns true if `lastPathPart(path)` starts with `.` and is not `.` or `..`.

  Note: paths are not normalized to determine `isHidden`.

  Examples:

      when defined(posix):
        assert ".foo".isHidden
        assert not ".foo/bar".isHidden
        assert not ".".isHidden
        assert not "..".isHidden
        assert not "".isHidden
        assert ".foo/".isHidden

  Source Edit

    proc getCurrentProcessId(): int {...}{.raises: [], tags: [].}

  Return current process ID.

  See also:

  - osproc.processID(p: Process)
  Source Edit

    proc setLastModificationTime(file: string; t: times.Time) {...}{.raises: [OSError], tags: [].}

  Sets the `file`'s last modification time. `OSError` is raised in case of an error. Source Edit

# Iterators

    iterator parentDirs(path: string; fromRoot = false; inclusive = true): string {...}{.
        raises: [], tags: [].}

  Walks over all parent directories of a given `path`.

  If `fromRoot` is true (default: false), the traversal will start from the file system root diretory. If `inclusive` is true (default), the original argument will be included in the traversal.

  Relative paths won't be expanded by this iterator. Instead, it will traverse only the directories appearing in the relative path.

  See also:

  - parentDir proc

  Examples:

      let g = "a/b/c"

      for p in g.parentDirs:
        echo p
      # a/b/c
      # a/b
      # a

      for p in g.parentDirs(fromRoot=true):
        echo p
      # a/
      # a/b/
      # a/b/c

      for p in g.parentDirs(inclusive=false):
        echo p
      # a/b
      # a

  Source Edit

    iterator envPairs(): tuple[key, value: TaintedString] {...}{.tags: [ReadEnvEffect],
        raises: [].}

  Iterate over all environments variables.

  In the first component of the tuple is the name of the current variable stored, in the second its value.

  See also:

  - getEnv proc
  - existsEnv proc
  - putEnv proc
  Source Edit

    iterator walkPattern(pattern: string): string {...}{.tags: [ReadDirEffect],
        raises: [OSError].}

  Iterate over all the files and directories that match the `pattern`.

  On POSIX this uses the glob call. `pattern` is OS dependent, but at least the `"*.ext"` notation is supported.

  See also:

  - walkFiles iterator
  - walkDirs iterator
  - walkDir iterator
  - walkDirRec iterator
  Source Edit

    iterator walkFiles(pattern: string): string {...}{.tags: [ReadDirEffect], raises: [OSError].}

  Iterate over all the files that match the `pattern`.

  On POSIX this uses the glob call. `pattern` is OS dependent, but at least the `"*.ext"` notation is supported.

  See also:

  - walkPattern iterator
  - walkDirs iterator
  - walkDir iterator
  - walkDirRec iterator
  Source Edit

    iterator walkDirs(pattern: string): string {...}{.tags: [ReadDirEffect], raises: [OSError].}

  Iterate over all the directories that match the `pattern`.

  On POSIX this uses the glob call. `pattern` is OS dependent, but at least the `"*.ext"` notation is supported.

  See also:

  - walkPattern iterator
  - walkFiles iterator
  - walkDir iterator
  - walkDirRec iterator
  Source Edit

    iterator walkDir(dir: string; relative = false): tuple[kind: PathComponent, path: string] {...}{.
        tags: [ReadDirEffect], raises: [OSError].}

  Walks over the directory `dir` and yields for each directory or file in `dir`. The component type and full path for each item are returned.

  Walking is not recursive. If `relative` is true (default: false) the resulting path is shortened to be relative to `dir`. Example: This directory structure:

      dirA / dirB / fileB1.txt
           / dirC
           / fileA1.txt
           / fileA2.txt

  and this code:

      for kind, path in walkDir("dirA"):
        echo(path)

  produce this output (but not necessarily in this order!):

      dirA/dirB
      dirA/dirC
      dirA/fileA1.txt
      dirA/fileA2.txt

  See also:

  - walkPattern iterator
  - walkFiles iterator
  - walkDirs iterator
  - walkDirRec iterator
  Source Edit

    iterator walkDirRec(dir: string; yieldFilter = {pcFile}; followFilter = {pcDir};
                       relative = false): string {...}{.tags: [ReadDirEffect],
        raises: [OSError].}

  Recursively walks over the directory `dir` and yields for each file or directory in `dir`.

  If `relative` is true (default: false) the resulting path is shortened to be relative to `dir`, otherwise the full path is returned.

  Warning: Modifying the directory structure while the iterator is traversing may result in undefined behavior!

  Walking is recursive. `followFilter` controls the behaviour of the iterator:

  yieldFilter | meaning
  --- | ---
  `pcFile` | yield real files (default)
  `pcLinkToFile` | yield symbolic links to files
  `pcDir` | yield real directories
  `pcLinkToDir` | yield symbolic links to directories

  followFilter | meaning
  --- | ---
  `pcDir` | follow real directories (default)
  `pcLinkToDir` | follow symbolic links to directories

  See also:

  - walkPattern iterator
  - walkFiles iterator
  - walkDirs iterator
  - walkDir iterator
  Source Edit