W3cubDocs

/Nim

Module os

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

Exports

putEnv, /, splitFile, WriteDirEffect, ScriptExt, getTempDir, isRootDir, ReadDirEffect, envPairs, ==, parentDir, unixToNativePath, getEnv, addFileExt, $, getConfigDir, joinPath, expandTilde, quoteShell, FileSystemCaseSensitive, quoteShellWindows, WriteEnvEffect, joinPath, CurDir, parentDirs, tailDir, AltSep, ReadEnvEffect, extractFilename, changeFileExt, ospaths, DynlibFormat, getHomeDir, osLastError, DirSep, PathSep, searchExtPos, OSErrorCode, existsEnv, quoteShellPosix, ExeExt, isAbsolute, raiseOSError, ExtSep, splitPath, cmpPaths, /../, doslikeFileSystem, osErrorMsg, quoteShellCommand, ParDir

Imports

strutils, times, winlean, ospaths

Types

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
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.
DeviceId = int32
FileId = int64
FileInfo = object
  id*: tuple[device: DeviceId, file: FileId]
  kind*: PathComponent
  size*: BiggestInt
  permissions*: set[FilePermission]
  linkCount*: BiggestInt
  lastAccessTime*: times.Time
  lastWriteTime*: times.Time
  creationTime*: times.Time
Contains information associated with a file object.

Consts

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

Procs

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)
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.
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.
proc fileExists(filename: string): bool {...}{.inline, raises: [], tags: [ReadDirEffect].}
Synonym for existsFile
proc dirExists(dir: string): bool {...}{.inline, raises: [], tags: [ReadDirEffect].}
Synonym for existsDir
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.
proc getLastModificationTime(file: string): times.Time {...}{.gcsafe, extern: "nos$1",
    raises: [OSError], tags: [].}
Returns the file's last modification time.
proc getLastAccessTime(file: string): times.Time {...}{.gcsafe, extern: "nos$1",
    raises: [OSError], tags: [].}
Returns the file's last read or write access time.
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.

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.
proc getCurrentDir(): string {...}{.gcsafe, extern: "nos$1", tags: [], raises: [OSError].}
Returns the current working directory.
proc setCurrentDir(newDir: string) {...}{.inline, tags: [], raises: [OSError].}
Sets the current working directory; OSError is raised if newDir cannot been set.
proc absolutePath(path: string; root = getCurrentDir()): string {...}{.raises: [ValueError],
    tags: [].}
Returns the absolute path of path, rooted at root (which must be absolute) if path is absolute, return it, ignoring root

Examples:

doAssert absolutePath("a") == getCurrentDir() / "a"
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.
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.

proc normalizedPath(path: string): string {...}{.gcsafe, extern: "nos$1", tags: [], raises: [].}
Returns a normalized path for the current OS. See #normalizePath
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 an exception 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.

proc sameFileContent(path1, path2: string): bool {...}{.gcsafe, extern: "nos$1",
    tags: [ReadIOEffect], raises: [Exception, IOError].}
Returns true if both pathname arguments refer to files with identical binary content.
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.
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.
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() 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.

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.
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.
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. Can be used to rename files
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. The proc does not return until the process has finished. To execute a program without having a shell involved, use the execProcess proc of the osproc module.

proc removeDir(dir: string) {...}{.gcsafe, extern: "nos$1",
                           tags: [WriteDirEffect, ReadDirEffect], gcsafe, locks: 0,
                           raises: [OSError, 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.

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.

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.

proc copyDir(source, dest: string) {...}{.gcsafe, extern: "nos$1",
                                 tags: [WriteIOEffect, ReadIOEffect], gcsafe,
                                 locks: 0,
                                 raises: [OSError, IOError, 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. To preserve attributes recursively on these platforms use copyDirWithPermissions().

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).

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).

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

Splits a command line into several components; This proc is only occasionally useful, better use the parseopt module.

On Windows, it uses the following parsing rules (see http://msdn.microsoft.com/en-us/library/17w5ykft.aspx ):

  • 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.

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() on non Windows platform. On Windows this proc is just a wrapper for copyFile() 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, errors while reading/setting file attributes will be ignored, otherwise will raise OSError.

proc copyDirWithPermissions(source, dest: string; ignorePermissionErrors = true) {...}{.
    gcsafe, extern: "nos$1", tags: [WriteIOEffect, ReadIOEffect], gcsafe, locks: 0,
    raises: [OSError, IOError, 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() on non Windows platforms. On Windows this proc is just a wrapper for copyDir() 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, errors while reading/setting file attributes will be ignored, otherwise will raise OSError.

proc inclFilePermissions(filename: string; permissions: set[FilePermission]) {...}{.
    gcsafe, extern: "nos$1", tags: [ReadDirEffect, WriteDirEffect], raises: [OSError].}
a convenience procedure for:
setFilePermissions(filename, getFilePermissions(filename)+permissions)
proc exclFilePermissions(filename: string; permissions: set[FilePermission]) {...}{.
    gcsafe, extern: "nos$1", tags: [ReadDirEffect, WriteDirEffect], raises: [OSError].}
a convenience procedure for:
setFilePermissions(filename, getFilePermissions(filename)-permissions)
proc moveDir(source, dest: string) {...}{.tags: [ReadIOEffect, WriteIOEffect],
                                 raises: [OSError].}
Moves a directory from source to dest. If this fails, OSError is raised.
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.

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() or retrieve all of them in one go with commandLineParams().

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

when declared(paramCount):
  # Use paramCount() here
else:
  # Do something else!
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(). Example:

when declared(paramStr):
  # Use paramStr() here
else:
  # Do something else!
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(). Example:

when declared(commandLineParams):
  # Use commandLineParams() here
else:
  # Do something else!
proc getAppFilename(): string {...}{.gcsafe, extern: "nos$1", tags: [ReadIOEffect],
                             raises: [].}

Returns the filename of the application's executable.

This procedure will resolve symlinks.

proc getAppDir(): string {...}{.gcsafe, extern: "nos$1", tags: [ReadIOEffect], raises: [].}
Returns the directory of the application's executable.
proc sleep(milsecs: int) {...}{.gcsafe, extern: "nos$1", tags: [TimeEffect], raises: [].}
sleeps milsecs milliseconds.
proc getFileSize(file: string): BiggestInt {...}{.gcsafe, extern: "nos$1",
    tags: [ReadIOEffect], raises: [OSError].}
returns the file size of file (in bytes). An OSError exception is raised in case of an error.
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, an error will be thrown.

proc getFileInfo(file: File): FileInfo {...}{.raises: [IOError, OSError], tags: [].}
creates an exception object of type exceptn and sets its msg field to message. Returns the new exception object.
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 structure will be slightly different across platforms, and in some cases, incomplete or inaccurate.

When followSymlink is true, 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, an error will be thrown.

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

Determines whether a given path is hidden or not. Returns false if the file doesn't exist. The given path must be accessible from the current working directory of the program.

On Windows, a file is hidden if the file's 'hidden' attribute is set. On Unix-like systems, a file is hidden if it starts with a '.' (period) and is not just '.' or '..' ' ."

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.

Iterators

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.

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.

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.

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 is returned. Walking is not recursive. If relative is true 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)

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

dirA/dirB
dirA/dirC
dirA/fileA1.txt
dirA/fileA2.txt
iterator walkDirRec(dir: string; yieldFilter = {pcFile}; followFilter = {pcDir}): string {...}{.
    tags: [ReadDirEffect], raises: [OSError].}

Recursively walks over the directory dir and yields for each file or directory in dir. The full path for each file or directory is returned. Warning: Modifying the directory structure while the iterator is traversing may result in undefined behavior!

Walking is recursive. filters controls the behaviour of the iterator:

yieldFilter meaning
pcFile yield real files
pcLinkToFile yield symbolic links to files
pcDir yield real directories
pcLinkToDir yield symbolic links to directories
followFilter meaning
pcDir follow real directories
pcLinkToDir follow symbolic links to directories

© 2006–2018 Andreas Rumpf
Licensed under the MIT License.
https://nim-lang.org/docs/os.html