civix: unix system library for Civstack
Civix contains standard unix functions that exist in most language's "sys"
library such as
sleep,
epoch etc. It also contains a powerful
Sh{}
type and convieience
sh() function for executing system shell commands,
either synchronously or asynchronously using the LAP protocol (see
lap.html.
TODO: better docs to come once the ele shell is finished
civix: unix-like OS utilities.
Types: Walk Sh ShFin
Functions
- fn mkdir
make a new directory, the parent must exist.
- fn dir(dir) -> iter[entry]
list entires in directory.
- fn rmdir(path) -> ok, errmsg, errno
remove empty directory
- fn exists(path) -> bool
return whether path exists.
- fn pathtype(path) -> str?, err
return path type (i.e. M.FILE, M.DIR, etc).
if path DNE then return (nil, errmsg).
- fn rm(path) -> nil
remove file.
- fn stat(v) -> Stat?, errmsg?
Given a path|File|Stat return a Stat
- fn statModifiedEq(fs1, fs2) -> boolean
return whether two Stat's have equal modification times
- fn modifiedEq(a, b)
return whether two path|File|Stat have equal modification times
- fn ls(dir) -> list[str]
Return the entries in a dir as a list.
They are sorted to put the directories first.
- fn mv(old, new)
Move path from old -> new, throwing an error on failure.
- fn fdWrite(to, from, sz--[[=BLOCK_SZ]]) -> (to, from)
Read data from fd from and write to fd to, then flush.
- fn cp(from, to)
copy data from from to to. Their types can be either
a string (path) or a file descriptor.
- fn swap(a, b, ext)
swap paths a <-> b
- fn setModified(f, sec, nsec) -> ok, errmsg?
set the modified time of the path|file
- fn quote(str)
quote the str if it's possible
- fn sleep(d) -> nil
Sleep for the specified duration
- fn epoch()
Return the Epoch/Mono time
Time according to realtime clock
- fn mono()
Duration according to monotomically incrementing clock.
- fn monoSec()
- fn pathEq(path1, path2)
return if the contents of the two paths are equal.
If both are directories return true (do not recurse).
If both don't exist return true
- fn isFile(path)
- fn isDir(path)
- fn walk(paths, ftypeFns, maxDepth)
TODO: remove this, use Walk instead.
walk the paths up to depth, calling ftypeFns[ftype] for
each item encountered.
If depth is nil/false then the depth is infinite.
ftypeFns must be a table of ftypes (file, dir) and:
- default: called as fallback (if missing ftype key)
- error: called if determining the type caused an error,
typically due to the file not existing.
the call is: error(path, errstr)
- dirDone: called AFTER the directory has been walked
The Fn signatures are: (path, ftype) -> stopWalk
If either return true then the walk is ended immediately
If dirFn returns 'skip' then the directory is skipped
- fn findBack(name, dir) -> path
Find the filename path going backwards.
- fn cpRecursive(from, to, except)
recursively copy from/ to new to/ directory.
- fn rmRecursive(path)
Recursively (force) remove the directory and all children.
- fn mkDirs(path)
Recursively (force) create the directory and any missing children.
- fn mkDir(path, parents)
Create a single directory. The parent must exist.
- fn forceCp(from, to)
copy from to to, creating the directory structure if necessary.
- fn forceWrite(path, text)
write text to path, creating the directory structure if necessary.
- fn forceMv(old, new)
Force move a file or directory, creating directory structure
if necessary.
- fn mkTree(dir, tree, parents)
mkTree(tree) builds a tree of files and dirs at `dir`
- Dirs are tables.
- Files are string or fd -- which are read+closed.
Example: tree = {
a = {
['a1.txt'] = 'stuff in a1.txt',
['a2.txt'] = 'stuff in a.txt',
a3 = {
['a4.txt'] = io.open'some/file.txt',
}
}
}
Builds a tree like
a/a1.txt # content: stuff in a1.txt
a/a2.txt # content: stuff in a2.txt
a/a3/a4.txt # content: stuff in a3.txt
- fn Lap()
civix's implementation of lap.Lap, enabling asynchronous file
reading/writing and async shell operations using pure lua coroutines.
- fn sh(M,'sh') -> out, err, Sh
Execute the command in another process via execvp (system shell). Throws an
error if the command fails.
if cmd is a table, the following keys are treated as special. If you need any
of these then you must use M.Sh directly (recommendation: use Plumb)
- stdin[string|file] the process's stdin. If string it will be sent to stdin.
- stdout[file] the process's stdout. out will be nil if this is set
- stderr[file] the process's stderr (default=io.stderr)
- ENV [table] the process's environment.
- CWD [table] the process's current directory.
- rc [bool] if true allow non-zero return codes (else throw error).
You can get the rc with sh:rc() (method on 3rd return argument).
Note: use Plumb{...}:run() if you want to pipe multiple shells together.
| Lua |
Bash |
| sh'ls foo/bar' |
ls foo/bar |
| sh{'ls', 'foo/bar', 'dir w spc/'} |
ls foo/bar "dir w spc/" |
| sh{stdin='sent to stdin', 'cat'} |
echo "sent to stdin" | cat |
- fn isRoot()
Walk the directory tree as a iterator of
path, ftype. Can walk either a
single path
Walk'path/' or a list of paths
Walk{'a/', 'b.txt'}.
- Note: all ftype=='dir' paths end in /.
- Warning: you may want to handle ftype=='error'
Usage:
local ix = require'civix'
local w = ix.Walk{'path/', 'path2/', 'file.txt'}
for path, pathTy in w do
if pathTy == 'dir' and path:match'skipMe' do
w:skip() -- skips the rest in this directory.
end
-- ... do something with each path.
end
Fields:
- maxDepth
maximum depth to walk (default=infinite)
- pi =0
the current (root) path index being walked
Methods
- fn:depth()
- get the depth of the current directory being walked
- fn:skip(self._dirs)
skip the current directory level
Start args on the shell
Suggestion: use civix.sh instead.
Sh:start() kicks off a subprocess which start the shell using the fds
you pass in or creating them if you set them to true. Created file
descriptors will be stored in the associated name.
Why? This means that :close() will only close filedescriptors created
by the shell itself, and you won't accidentially close
io.stdout/etc.
Examples (see civix.sh for more examples):
| Lua |
Bash |
| Sh({'ls', 'foo/bar'}, {stdout=io.stdout}):start() |
ls foo/bar |
| v = Sh{'ls foo/bar', stdout=true}:start():read'a' |
v=$(ls foo/bar) |
Fields:
- args
arguments to pass to shell
- stdin
shell's stdin to send (default=empty)
- stdout
shell's stdout (default=empty)
- stderr
shell's stderr (default=empty)
- env
shell's environment {'FOO=bar', ...}
- cwd
current working directory
Methods
Argument for
#civix.Sh.finish.
Fields:
test runners and helpers for civix
Functions