←  C Shell for Windows

Built-in commands

All 245 commands built into cshw. Type to filter the list; press Enter to jump to the first match.

CommandDescription
.Read and execute commands from file (alias for source).
@arithmetic assignment (csh-style)
[Evaluate a conditional expression (test, requires a closing ]).
aboutshow the CSHW About dialog
addcontroladd a child control to a script-owned window
adoptbring an already-running process under job control
aliascreate command aliases
arraycreate or manipulate an indexed array variable
attribdisplay or change file attributes
awkpattern-scanning and text-processing language
barrierrendezvous barrier for N participants
baseprint a number in another radix
base64encode or decode base64 data
basenamestrip directory and suffix from a path
bcarbitrary-precision calculator language
bgmove job to background
bindeventbind a script proc as a window event handler
bugreportcompose and send a bug report to bugs@tropibyte.com
cancelremove jobs from a print queue (System V spelling of lprm)
catconcatenate file(s) (or stdin) to standard output
cdchange the current working directory
chancreatecreate a message-passing channel (shorthand)
channelmessage-passing channel between coroutines
chdirchange the current working directory (alias for cd)
checkmailcheck $mail now for new messages
chmodchange file permissions
chownchange file owner
clipcopy to clipboard
clsclear the console screen
cmdliblistlist loaded command libraries
cocancelcancel a running coroutine
cocasatomic compare-and-swap on a thread-safe variable
cocleanremove completed coroutines from tracking
codecratomically decrement a thread-safe variable
cogetread a thread-safe atomic variable
coincratomically increment a thread-safe variable
colistlist coroutines and their status
completedefine tab completion rules
copycopy files
coresultget the result of a completed coroutine
coresumeresume a suspended coroutine
corunprocstart a procedure as a concurrent coroutine
cosetset a thread-safe atomic variable
cosuspendsuspend a running coroutine
cowaitwait for coroutine(s) to complete
cpcopy files (alias for copy)
createwindowcreate a script-owned window on the UI thread
crondcron daemon control
crontabmanage scheduled cron jobs
cutremove sections from each line
datedisplay or format the current date and time
dcreverse-Polish arbitrary-precision calculator
declaredeclare a variable with optional type / scope flags
deldelete files
dfdisplay disk free space
diffcompare files line by line
dirdisplay directory contents
dirnamestrip the last component from a path
dirsdisplay directory stack
disownrelease a job without stopping the process
dllimportload DLL for function calls
dlllistlist imported DLLs
dllunloadunload a previously imported DLL
duestimate file space usage
echodisplay text or variable values
enableEnable or disable a built-in (bash's spelling of shadow).
endsplashdismiss the modeless splash dialog
envdisplay or modify environment
evalconcatenate arguments and run the result as a command
eventmanual/auto-reset event signal
exampleShow or run a bundled example script.
execreplace shell with command
exitexit the shell
falsereturn failure (documented with true)
fetchtransfer data from a URL (HTTP/HTTPS/FTP client)
fgmove job to foreground
fileidentify file type
file-renamerename files with a Perl-style expression
fileblobencode a file into a one-line text blob
findsearch for files in a directory tree
fmtreflow paragraphs to a width
foldwrap long lines to a fixed width
ftpfetchFTP file transfer client
genaiinteract with AI language models
globexpand filename patterns
grepsearch for patterns in files
hashcreate or manipulate an associative array (hash) variable
hashstatdisplay command hash table statistics
headoutput the first part of files
helpdisplay command help
hexdumpdisplay file contents in hexadecimal
historydisplay command history
hostnamedisplay the system hostname
installinstall cshw onto the system
isWindowstest whether the shell is running on Windows
jobsdisplay status of background jobs
kadkill process and secure-delete its executable (alias for killanddel)
killterminate processes
killanddelkill processes and securely delete executables
lccount lines in files
libraryload CSHW script as procedure library
limitdisplay resource limits
linecountcount lines in files (alias for lc)
localdeclare a variable in the current procedure's scope
logtee stdout and stderr to a file while still showing them
loginlog in as a different user
logoutend a login shell
lpsend a file to a printer, or render it to a file
lpadminPrinter administration.
lpccontrol a print queue
lpqlist the jobs in a print queue
lprsend a file to a printer (BSD spelling of lp)
lprmremove jobs from a print queue
lpstatshow printers and what they will accept
lslist directory contents (native, not a shell-out)
mandisplay manual pages
mdmake a directory (alias for mkdir)
md5sumcompute MD5 message digest
messageboxshow a Win32 message box
mkdircreate directories
mklinkcreate symbolic and hard links
moredisplay text one screen at a time
msgboxdisplay a message box
mutexmutual-exclusion lock
mvmove or rename files and directories
nicerun command with modified priority
nlnumber the lines of a file
nohuprun command immune to hangups
nopno operation (alias for true)
notifyenable job completion notifications
onintrset interrupt handler
passwordread a password from the console (no echo)
passworddlgprompt for a password using a modal dialog
pathmapmap Unix-style paths to Windows destinations
peinfodisplay PE file information
popdpop directory from stack and change to it
postmessagepost a Win32 message to a window's queue (async)
prpaginate text for printing
prenamerename files with a Perl-style expression
printenvprint environment variables
printfformat and print arguments
processlistlist running processes
progressdlgshow and drive a modeless progress dialog
promptset or display command prompt
psLists all the processes running on the system (alias for processlist).
pushdpush directory onto stack and change to it
pwdprint working directory
quicsrvlaunch and supervise quicsrv QUIC/UDP (HTTP/3) server worker processes
rclregister command library (load plugin DLL)
rdremove a directory (alias for rmdir)
readfileread a file's contents into a shell variable
readonlymake a variable read-only
realpathprint the absolute, canonical form of a path
registercmdlibregister command library (load plugin DLL)
registryin-shell Windows Registry operations
rehashrebuild command lookup hash table
renamerename a file, or substitute in many file names
repeatrun a command a given number of times
retprocreturn from the current procedure with a value
retshellexit a sourced script without killing the shell
revreverse lines character by character
rmremove files
rmdirremove directories
rundllproccall an exported function from a DLL
sayprint a system value (time, date, hostname, etc.) and capture it
sedstream editor for filtering and transforming text
semaphorecounting semaphore
semcreatecreate a counting semaphore (shorthand)
sendmessagesend a Win32 message to a window (synchronous)
seqprint sequence of numbers
servicemanage Windows services
setset or display shell variables
setenvset environment variable
sha1sumcompute SHA-1 message digest
sha256sumcompute SHA-256 message digest
sha512sumcompute SHA-512 message digest
shadowhide a built-in so a program of the same name runs instead
shareassign a variable in the global namespace (write-through)
shasumcompute or verify a SHA hash with a selectable algorithm
shiftshift positional parameters
shutdownshutdown, restart, or log off the system
sleeppause the current thread of execution for a duration
socketlow-level socket operations
sortsort lines of text
sourceexecute commands from a file in the current shell
spawnstart another cshw instance in a new console window
splashshow a modeless splash dialog during a long-running step
splitpathprint the components of a path, one per line
startstart a program or open a file
statdisplay file status information
stopsuspend a running job
stringsextract printable strings from files
sudorun command as Administrator
suspendmanage system power state from the shell
synclist and destroy synchronization objects
tacconcatenate and print files in reverse line order
tailoutput the last part of files
tararchive files
tctime how long a command takes to run
tcpclientone-shot TCP client
tcpserverstart a TCP server
teeread from stdin and write to stdout and files
testevaluate a conditional expression
testsplash[INTERNAL] exercise the splash dialog in a chosen mode
timemeasure command execution time
timeoutrun command with time limit
titleset or display the console window title
tokenizedisplay parsed tokens from input
touchchange file timestamps or create empty files
trtranslate or delete characters
treedisplay a directory structure graphically
truesucceed or fail with no side effects
tsrvdlaunch and supervise tsrvd server worker processes
typedisplay file contents
umaskset file creation mode mask
unaliasremove command aliases
unameprint system information
unbindeventremove a window event binding
uncompleteremove tab completion rules
unfileblobdecode a fileblob back into a file
unhashremove command from hash table
uniqreport or filter out repeated lines
unlimitreport that resource limits cannot be removed
unregistercmdlibunregister command library (unload plugin DLL)
unsetremove shell variables
unsetenvremove environment variable
unshadowrestore a built-in hidden by shadow
unzipextract or list a .zip archive
uptimeshow how long system has been running
urclunregister command library (unload plugin DLL)
vartypedisplay variable type
verdisplay shell version (alias for version)
versiondisplay shell version
voldisplay a volume's label and serial number
waitWait for all running coroutines (alias for `cowait /all`).
watchexecute command periodically
wcword, line, character, and byte count
wherelocate every place a command name resolves
whichlocate a command
whoamidisplay current user name
winapicall a Win32 API by name with auto-resolution of its DLL
winverdisplay Windows version
writefilewrite a shell variable's contents to a file
xargsbuild command lines from standard input and run them
zipcreate a .zip archive (Windows-style)

. back to top ↑

Read and execute commands from file (alias for source).

No detailed man page yet — see the one-line summary above.

@ back to top ↑

arithmetic assignment (csh-style)

Synopsis

    @ VAR = EXPRESSION
    @ VAR <op>= EXPRESSION       # += -= *= /= %= &= |= ^= <<= >>=
    @ VAR++ | @ VAR--

Description

Evaluates EXPRESSION and assigns the result to the shell variable VAR. csh-style in spirit but with C-style precedence and left associativity, so `2 + 3 * 4` is 14, not 20. Integer operands keep integer results; a float operand or a math primitive promotes the result to floating point. Compound-assign forms (+=, -=, ...) and the ++ / -- forms update VAR in place.

Constants: pi, e, tau.

Options

    Operators (high to low precedence):
      unary   - + ! ~
      * / %       (modulo is integer; use fmod(a,b) for floats)
      + -
      << >>       (integer)
      < <= > >=
      == !=
      & ^ |       (integer bitwise)
      && ||

    Math primitives:
      trig:        sin cos tan  asin acos atan  atan2(y,x)
      hyperbolic:  sinh cosh tanh
      logs/exp:    log (= ln) log10 log2  exp
      powers:      sqrt cbrt  pow(b,e)  hypot(a,b)  root(x,n)
      rounding:    floor ceil round trunc  fmod(a,b)
      misc:        abs sign  min(a,b) max(a,b)

Examples

    @ count  = 0
    @ count++
    @ result = 5 + 3
    @ angle  = pi / 4
    @ x      = sin(angle) * sqrt(2)
    @ fourth = root(256, 4)        # 4.0  (same as pow(256, 0.25))
    @ deg    = atan2(1, 1) * 180 / pi

Exit status

0       Assigned.
>0      Parse/evaluation error (e.g. division by zero, bad expression).

See also

set, bc, dc, expr

[ back to top ↑

Evaluate a conditional expression (test, requires a closing ]).

No detailed man page yet — see the one-line summary above.

about back to top ↑

show the CSHW About dialog

Synopsis

    about [/min | /minimal | /nerdy | /nerd | /lyrical]

Description

Displays a modal About dialog showing the CSHW version and copyright information. The dialog appears on the UI thread, falling back to a self-contained modal pump when CSHW is running in non-interactive mode.

Options

    /lyrical    (default) Short tagline + credits.
    /min        Minimal -- title, version, and copyright only.
    /minimal    Same as /min.
    /nerdy      Verbose -- build date/time, compiler, architecture,
                bundled library versions.
    /nerd       Same as /nerdy.

Examples

    about
        Show the default (lyrical) variant.

    about /nerdy
        Show build details for diagnostic / bug-report purposes.

Exit status

0       Always (the dialog closes silently).

See also

version, splash, passworddlg

addcontrol back to top ↑

add a child control to a script-owned window

Synopsis

    addcontrol <type> <parent_hwnd> [<text>]
               [/pos:x,y] [/size:w,h] [/id:<n>] [/style:extra]

Description

Creates a standard Win32 child control inside a parent window (typically one made by `createwindow`). Type-aware defaults handle the class name and the common style bits; you only specify position, size, id, and text. The created control is auto-subclassed so `bindevent` against it Just Works.

Options

    <type>      One of:
                  button     -- BS_PUSHBUTTON | WS_TABSTOP
                  defbutton  -- BS_DEFPUSHBUTTON | WS_TABSTOP
                  checkbox   -- BS_AUTOCHECKBOX | WS_TABSTOP
                  radio      -- BS_AUTORADIOBUTTON | WS_TABSTOP
                  groupbox   -- BS_GROUPBOX
                  label      -- STATIC SS_LEFT
                  edit       -- EDIT ES_AUTOHSCROLL | WS_BORDER | WS_TABSTOP
                  textarea   -- EDIT multi-line, vertical scroll
                  listbox    -- LISTBOX LBS_NOTIFY | WS_VSCROLL
                  combobox   -- COMBOBOX CBS_DROPDOWNLIST | WS_VSCROLL
                  progress   -- msctls_progress32
    <parent_hwnd>
                Parent window HWND (hex or decimal).
    <text>      Initial text / button label.
    /pos:x,y    Position relative to parent client area. Default: 0,0.
    /size:w,h   Control size. Default: 100x24.
    /id:<n>     Control id (the LOWORD of wParam in WM_COMMAND). Default 0.
    /style:extra
                Additional WS_* / BS_* / ES_* etc. bits to OR in.
                WS_CHILD | WS_VISIBLE are always set automatically.

Examples

    createwindow "" "Form" /size:300,200
    set w = $result
    addcontrol label    $w "Name:"  /pos:10,10  /size:60,20
    addcontrol edit     $w ""       /pos:80,10  /size:200,20 /id:1
    addcontrol button   $w "&OK"    /pos:100,150 /size:80,25  /id:100

    proc on_ok
        echo "OK clicked"
    endproc
    bindevent $w command 100 on_ok

Exit status

0       Success; $result is the new control HWND in hex.
1       Unknown control type, bad args, or UI thread unavailable.

See also

createwindow, bindevent, unbindevent

adopt back to top ↑

bring an already-running process under job control

Synopsis

    adopt PID

Description

Adds a process cshw did not start to this shell's job table, so the ordinary job-control verbs work on it: jobs, stop, bg, fg, kill, wait, and the %n job specifications.

Find the PID with 'ps' (or 'processlist'), then adopt it.

The process keeps running throughout; adopting it changes nothing about the process itself, only what this shell knows about it.

Options

    PID             Process ID to adopt. Must be a live process.

Examples

    ps | grep notepad
        # notepad.exe    41288
    adopt 41288
        # [1] 41288  C:\WINDOWS\system32\notepad.exe

    adopt 41288
    stop %1
        Freeze it.

    bg %1
        Let it run again.

    disown %1
        Release it from job control, leaving it running.

Exit status

0       Adopted
1       No such process, already adopted, access denied, or the
        process has already exited

Notes

Differences from a process cshw launched itself:

- No targeted signal. cshw gives processes it starts their own process group, which is how a graceful 'kill' reaches them directly. An adopted process is not in such a group, so a graceful kill can only try WM_CLOSE. The console-broadcast fallback is deliberately NOT used on adopted processes: it requires detaching cshw from its own console, and a failed reattach leaves the shell with no console at all.

- 'fg' waits for the process to exit, but it was never attached to this console, so "foreground" means only that cshw is blocked until it ends.

- Adopting a process running at higher integrity requires an elevated cshw. Without it, OpenProcess fails and adopt reports access denied rather than half-succeeding.

- If the process cannot be assigned to a job object, adopt still succeeds but says so: stop and bg then act on that process alone rather than on it and its children.

cshw refuses to adopt its own process.

See also

disown, jobs, stop, bg, fg, kill, ps

alias back to top ↑

create command aliases

Synopsis

    alias
    alias NAME=COMMAND
    alias NAME COMMAND

Description

Creates a shortcut name for a command or displays existing aliases. Aliases allow you to create shorter or more memorable names for frequently used commands or command sequences.

When a command is entered, CSHW first checks if it's an alias before looking for built-in commands or external programs. This allows aliases to override default behavior.

Options

    NAME            The alias name to create.
    COMMAND         The command the alias expands to.

Examples

    alias
        Display all defined aliases.

    alias ll=dir
        Create 'll' as an alias for 'dir'.

    alias la="dir /a"
        Create 'la' for 'dir /a' (show all including hidden).

    alias cls=clear
        Make 'clear' work like 'cls'.

    alias ..="cd .."
        Create '..' to go up one directory.

    alias ...="cd ..\.."
        Create '...' to go up two directories.

    alias h=history
        Short alias for history command.

    alias g=grep
        Short alias for grep command.

    alias projects="cd C:\Users\Me\Projects"
        Quick navigation alias.

Exit status

0       Success
1       Invalid alias name
2       Syntax error

Notes

Alias Persistence: Aliases are not persisted across shell sessions. To make aliases permanent, add them to your shell startup script. On interactive startup, CSHW loads %USERPROFILE%\.cshrc first; if it is missing, it falls back to %APPDATA%\cshw\cshwrc.

Alias Expansion: Aliases are expanded before command execution. An alias can include switches and arguments.

Resolution order: proc > alias > built-in > PATH

An alias beats a built-in, as it does in tcsh and bash. That is what makes `alias ls 'ls -l'` do anything at all. A procedure beats both.

Recursion: An expansion is re-scanned, so aliases chain:

alias ll "ls -l"
alias lla "ll -a"        # ll expands too

The exception is what makes the commonest alias in existence terminate: if the FIRST WORD of an expansion is the alias being expanded, it is not expanded again. So

alias ls "ls -l"

becomes `ls -l` exactly once, and that `ls` reaches the built-in rather than looping. A genuine cycle across different names -- `alias a b` with `alias b a` -- is caught by a depth limit and reported as "Alias loop."

Getting past an alias: There is no backslash escape here. tcsh lets you type \ls to bypass an alias for one command; in cshw that does nothing special. Use the full path, or unalias the name. To hide a BUILT-IN so a program of the same name runs instead, that is a different tool: see shadow(1).

See also

unalias, set, history, which, where, shadow

array back to top ↑

create or manipulate an indexed array variable

Synopsis

    array <name>
    array <name> <value1> <value2> ... <valueN>
    array set  <name> <index> <value>
    array get  <name> <index>
    array push <name> <value>
    array size <name>
    array list <name>

Description

Creates an indexed array variable. With only a name, creates an empty array. With trailing values, initializes the array with those elements.

SUBSCRIPTS ARE 1-BASED, as they are in csh: element 1 is the first. That holds everywhere -- `$name[1]`, `set name[1] = v`, `array set name 1 v`, `array get name 1`, and the indices `array list` prints.

`[0]` IS OUT OF RANGE, as it is in tcsh, on every one of those paths. It was tolerated as `[1]` for a while, as a bridge for an earlier printing of the book which described the arrays as 0-based because the first implementation was. A second numbering scheme is what made the off-by-one hard to see, so the bridge is gone: write 0 and you are told, rather than reading element 1 and never finding out.

`loop`'s counter and $loopindex are 1-based too, so `loop $#a as i` pairs with `$a[$i]` directly and reads every element. `for` and `while` are unchanged and still let you choose your own bounds.

`array set` and `array get` used to take the index as 0-based storage while `$name[n]` was 1-based, so `array set c 2 X` wrote element 3 and `set c[2] = Y` wrote element 2 -- two bases for the same array, with nothing to say which had just been used.

Elements are read with `$name[<i>]` and written with `set name[<i>] = <value>` or `array set`. `array push` appends.

Re-declaring an array with no values keeps its contents, so a script that declares its arrays at the top can be sourced twice. Re-declaring WITH values replaces them.

Options

    <name>      Array name. Same rules as scalar variable names.
    <values>    Optional initial elements.

    set NAME INDEX VALUE    Set element INDEX (1-based).
    get NAME INDEX          Print element INDEX and set $result to it.
    push NAME VALUE         Append VALUE as a new last element.
    size NAME               Print the number of elements.
    list NAME               Print every element as "[i] = value".

Examples

    array colors red green blue
    echo "first is $colors[1]"        # red
    echo "count = $#colors"           # 3

    array set colors 2 GREEN          # element 2, not 3
    array push colors yellow
    array list colors                 # [1] = red ... [4] = yellow

    array empty
    set empty[1] = "first"
    set empty[2] = "second"
    echo "count = $#empty"            # 2

    # Iteration:
    foreach c ($colors)
        echo $c
    end

Exit status

0       Array declared / updated / reported.
1       Bad name, an index that is not a number, an unknown
        subcommand, or a variable that is not set.

An index that will not parse is an ERROR, not element 1. `array set c oops X` used to overwrite the FIRST element and return 0 -- a typo silently corrupting data and reporting success.

`array list` and `array size` report a variable that is not set rather than printing nothing or 0. `$#name` still expands to 0 for an unset name: an EXPANSION yields a value into a larger expression, a COMMAND performs an action and has a status to say how it went.

Notes

Every variable is subscriptable: Subscripting is by WORD and works on any variable, not just ones made with `array` or with parentheses -- csh's only variable is a word list, and a plain string is a one-word list:

set e = one
echo $e[1]        ->  one
echo $#e          ->  1

So `$name[1]` is safe on a variable you did not build as an array. It used to return the first CHARACTER for a non-array, which made the subscript mean different things depending on a type the script could not see.

For characters rather than words, use the substring form ${var:off:len}, which is 0-indexed. See `man set`.

For string-keyed (associative) arrays, see `hash`. Both styles are distinct: an indexed array uses integer indices in [], a hash uses string keys in {}.

See also

hash, set, unset, declare, foreach

attrib back to top ↑

display or change file attributes

Synopsis

    attrib FILE
    attrib [+|-]ATTR FILE

Description

Displays or modifies file attributes. Windows files have several attributes that control visibility, backup status, and system protection.

Options

    FILE            File(s) to examine or modify.

    Attributes (prefix with + to set, - to clear):
    R               Read-only - prevents modification
    H               Hidden - not shown in normal listings
    S               System - marks as system file
    A               Archive - file needs backup

    /s              Process files in subdirectories.
    /d              Process directories as well as files.

Examples

    attrib file.txt
        Display attributes of file.txt.

    attrib +R important.doc
        Make file read-only.

    attrib -R important.doc
        Remove read-only attribute.

    attrib +H secret.txt
        Hide a file.

    attrib -H -S file.txt
        Remove hidden and system attributes.

    attrib -R /s *.txt
        Remove read-only from all .txt files recursively.

    attrib +A /s *.*
        Mark all files as needing backup.

Exit status

0       Success
1       File not found
2       Access denied

Notes

Attribute Meanings: R (Read-only) - Prevents file modification. Must be cleared before editing or deleting the file. H (Hidden) - File won't appear in normal dir listings. Use 'dir /ah' to show hidden files. S (System) - Marks file as system file. Often combined with Hidden for Windows system files. A (Archive) - Indicates file has changed since last backup. Backup software uses this to detect changes.

Combining Attributes: You can set or clear multiple attributes at once: attrib +R +H file.txt

Protected System Files: Some system files have both +S and +H and may require special handling to modify.

See also

stat, dir, chmod

awk back to top ↑

pattern-scanning and text-processing language

Synopsis

    awk [OPTIONS]... 'PROGRAM' [FILE]...
    awk [OPTIONS]... -f SCRIPT-FILE [FILE]...
    command | awk [OPTIONS]... 'PROGRAM'

Description

awk reads text from one or more input files (or standard input), splits each line into fields, and runs a program of pattern-action rules against every line. It is the classic Unix tool for column-oriented text processing -- extracting columns, computing sums, reformatting delimited data, and producing reports.

cshw's awk implements a substantial POSIX awk subset, with PCRE2 as the regex engine (so lookahead, lookbehind, and Unicode classes all work) and dual Windows-style and Unix-style switch spellings. Programs run top-to-bottom over each input record: the BEGIN block fires once before input, the END block fires once after, and rule patterns select which records each action applies to.

Options

    -F SEP, --field-separator=SEP, /F:SEP
                Set the input field separator. SEP can be a single
                character, a regex, or the special value " " (default,
                which splits on runs of whitespace AND trims leading/
                trailing whitespace from each record).

    -f FILE, --file=FILE, /f:FILE
                Read the awk program from FILE instead of from the
                command line. Multiple -f options are accepted; their
                contents are concatenated.

    -v VAR=VALUE, --assign VAR=VALUE, /v:VAR=VALUE
                Predefine an awk variable before execution. Repeatable.
                The assignment happens after BEGIN's first variable
                lookup, so -v sets variables visible to BEGIN.

Switch aliases:
    cshw accepts both Unix-style (-x / --xxx) and Windows-style (/x:val)
    spellings everywhere. So `-F,`, `--field-separator=,`, and
    `/F:,` are all equivalent.

.AWK PROGRAM LANGUAGE

An awk program is one or more pattern-action rules of the form:

    PATTERN { ACTION }

Both PATTERN and ACTION are optional. A bare pattern with no action
defaults to `{ print }`. A bare action with no pattern runs on every
record. Rules are separated by newlines or semicolons.

Patterns

    BEGIN           Runs once, before any input is read.
    END             Runs once, after all input is consumed.
    BEGINFILE       Runs before the first record of EACH input file.
                    FILENAME is already set and FNR is 0. If the file
                    could not be opened, this still runs, with ERRNO
                    describing why -- and `nextfile` here skips the file
                    instead of letting the error stop the run.
    ENDFILE         Runs after the last record of each input file. It
                    runs for a file cut short by `nextfile`, and for an
                    empty one, because those files still ended. It does
                    NOT run for a file that never opened, nor for the
                    file in hand when `exit` is called.
    /REGEX/         Matches when the current record matches REGEX.
    EXPR            Matches when EXPR evaluates to a true value (any
                    non-zero number or non-empty string).
    EXPR1, EXPR2    Range pattern: matches from a record where EXPR1
                    is true through the next record where EXPR2 is
                    true (inclusive). Ranges latch.
    !PATTERN        Negation: matches when PATTERN does not.

.FIELDS AND RECORDS
    A record is a line by default. The record is split into fields by FS:
        $0      The whole record.
        $1, $2... Individual fields, 1-indexed.
        $NF     The last field.
        $(NF-1) Second-to-last field, etc.

    Assigning to a field updates $0 (joined with OFS); assigning to NF
    truncates or pads the field list.

.BUILT-IN VARIABLES
    NR          Total record number across all inputs.
    FNR         Record number within the current file (resets on each).
    NF          Field count of the current record.
    FS          Input field separator (default: " ").
    OFS         Output field separator for `print` (default: " ").
    ORS         Output record separator for `print` (default: "\n").
    RS          Input record separator (default: "\n").
    FILENAME    Name of the current input file ("-" for stdin).
    CONVFMT     Format used when a NUMBER becomes a string in
                CONCATENATION or as an array subscript (default "%.6g").
    OFMT        Format used when a number is printed by `print`
                (default "%.6g"). CONVFMT and OFMT are separate knobs on
                purpose: `x ""` and `print x` can differ.
                NEITHER applies to an integral value -- 1e17 prints as
                100000000000000000, not 1e+17, whatever they are set to.
    ARGC        Operand count, including ARGV[0].
    ARGV        ARGV[0] is "awk"; ARGV[1..] are the operands in the order
                given -- file names AND var=value assignments -- so
                `for (i = 1; i < ARGC; i++)` walks the inputs.
    ENVIRON     The process environment, keyed by variable name:
                ENVIRON["PATH"]. Built on first use.
    ERRNO       Why the last input file failed to open, as text
                ("No such file or directory"), or empty when it opened.
                Set before BEGINFILE runs, which is where it is meant to
                be read.
    RSTART      Position of last regex match (set by match()).
    RLENGTH     Length of last regex match (-1 if no match).
    SUBSEP      Separator used to join a multi-dimensional subscript:
                `a[i,j]` is one element keyed by i SUBSEP j. Default is
                . Reassigning it changes the join, and
                `split(key, parts, SUBSEP)` is how you take such a key
                apart again. The join always used  and the variable
                was never published, so SUBSEP read as the empty string
                and that split returned single characters.

Getline

    getline                 Read the next record from the main input.
                            Sets $0, NF, NR, FNR.
    getline var             ...into var instead. Sets NR, FNR.
    getline < file          Read a record from file. Sets $0, NF.
    getline var < file      ...into var. Sets nothing else.
    "cmd" | getline         Run cmd, read a record of its output.
                            Sets $0, NF.
    "cmd" | getline var     ...into var. Sets nothing else.

    Returns 1 when a record was read, 0 at end of input, and -1 when
    the source could not be opened. The usual shape is therefore:

        while ((getline line < "config.txt") > 0) { ... }

    A plain `getline` shares the driver's position, so a record it
    consumes is one the main loop will not see again -- which is what
    makes `{ getline; print }` print every OTHER record.

    That position spans every input operand, so a `getline` at the end
    of one file rolls into the next: FILENAME changes, FNR restarts, NR
    carries on, and the file being left gets its ENDFILE while the one
    being entered gets its BEGINFILE. It returns 0 only at the end of
    the LAST file.

    Reads from the same source advance: two `getline < "f"` calls give
    the first and second records. A source that fails to open keeps
    returning -1 rather than being retried on every call.

    The command forms do NOT move NR. That follows GNU, and diverges
    from the POSIX table which lists NR for them; matching the standard
    instead would disagree with every script written against gawk.

    "cmd" runs through CSHW, so it reaches the same commands the rest of
    the shell has -- builtins included, and whole pipelines:

        "echo abc | rev" | getline r        # r is "cba"

    Nothing routes to cmd.exe or PowerShell unless system() is asked for
    one by name.

.BUILT-IN FUNCTIONS
    String:
        length(s)               Length in characters.
        substr(s, start [, n])  Substring (1-indexed).
        index(haystack, needle) 1-indexed position, 0 if not found.
        split(s, arr [, sep])   Split into array, return field count.
        sub(re, repl [, target])  Replace first match in target (default $0).
        gsub(re, repl [, target]) Replace all matches.
        match(s, re)            Set RSTART/RLENGTH; return position.
        tolower(s), toupper(s)
        sprintf(fmt, ...)       printf-style formatting; returns string.

    Numeric:
        int(x)                  Truncate to integer.
        sqrt(x), exp(x), log(x)
        sin(x), cos(x), atan2(y, x)
        rand()                  Pseudo-random in [0, 1).
        srand([seed])           Seed rand; default is wall-clock.

    Time:
        systime()               Seconds since the Unix epoch.

    Process and stream:
        close(expr)             Close a file or command opened by print
                                redirection or by getline. Returns 0 if
                                something was closed, -1 if that name was
                                never open.
        system([shell, ] cmd)   Run a command, wait, return its exit
                                status. See the SYSTEM section.

    I/O:
        print [arg, arg, ...]   Output args joined by OFS, terminated by ORS.
        printf fmt, args...     printf-style; no trailing ORS unless in fmt.

    printf conversions: %s %d %i %u %f %e %g %x %X %o %c %%
    Flags: - + space 0 #

    Width and precision may each be a number or `*`, which takes the
    value from the next argument -- `printf "%*d", 5, 42` pads to five,
    and `printf "%*.*f", 8, 2, x` takes both. The `*` form was
    documented and never parsed; the literal text `%*d` came out.

    %c prints the CHARACTER whose code is the argument when the argument
    is a number, and the first character when it is a string. The
    distinction is the value's origin, not how it looks: "65" is a
    string and gives "6", while 0+65 gives "A". A numeric argument used
    to take the string path and print its first digit.

Statements

    Control flow: if/else, while, do/while, for(init;cond;step),
    for (key in array), break, continue, next, nextfile, exit [N],
    return.

        next        Stop processing this record; go to the next one.
        nextfile    Stop processing this record AND the rest of the
                    current input file; go on to the next file. On
                    standard input, where there is no next file, it ends
                    the input.
        exit [N]    Stop reading input and run END, then exit with N.
                    exit inside END stops immediately. A bare `exit`
                    leaves the status unchanged, so
                    `BEGIN{exit 3} END{exit}` still exits 3.

    Arrays: associative; created by first reference. `delete arr[k]`
    removes a single element; `delete arr` clears the whole array.
    Membership is `key in arr`, and for a multi-dimensional subscript
    `(i, j) in arr` -- which tests the same composite key `arr[i, j]`
    creates.

    Comments: `# ...` runs to end of line.

System

    system([SHELL, ] COMMAND)

    Runs COMMAND, waits for it, and returns its exit status. awk's own
    buffered output is flushed first, so `print "a"; system("echo b")`
    really does print a before b. The command's output goes wherever
    awk's output goes, including into a `> file` redirection or a
    captured pipeline.

    The one-argument form runs COMMAND through CSHW. That is the more
    compatible choice, not the parochial one: awk programs in the wild
    are written against a Unix shell and call things like
    system("rm -f " tmp), and cshw has rm where cmd.exe does not, so a
    script ported from Unix stands a chance of running unchanged.

    The two-argument form names the shell. Names are case-insensitive
    and each shell answers to several spellings:

        cshw | csh | cshell | tcsh    the running cshw   (the default)
        cmd  | command                cmd.exe /c
        ps   | powershell | pwsh      pwsh if present, else powershell
        bash | sh                     bash.exe, if it is installed

        system("ls -l")                    through cshw
        system("cmd",  "dir /w")           through cmd.exe
        system("ps",   "Get-Process")      through PowerShell
        system("bash", "ls | wc -l")       through bash

    cshw is located by module path, not by PATH, so an awk script always
    gets the same build of the shell that is interpreting it -- and a
    portable install that is not on PATH still works.

    The same routing applies to awk's own pipe operators, `print | "cmd"`
    and `"cmd" | getline`. Those went to cmd.exe until 1.0.8.5, which
    meant a cshw builtin was unreachable from inside a cshw script:
    `echo abc | rev` worked at the prompt and answered "'rev' is not
    recognized" inside awk.

    bash is allowed to FAIL rather than fall back to another shell:
    running bash syntax under cmd.exe would not report an error, it
    would run something else. An unknown shell name is an error too.

.FIELD SPLITTING
    Field splitting and split() are the same operation with different
    destinations, and they follow one set of rules, decided in this
    order:

        FS == " "       the default: split on runs of whitespace, with
                        leading and trailing whitespace ignored
        FS == ""        one field per character
        one character   LITERAL, never a regex -- which is what makes
                        FS="." split on dots rather than everywhere
        anything longer an ERE

    split(s, arr, sep) takes the same forms, and additionally accepts a
    REGEX LITERAL, which is always treated as a regex whatever its
    length:

        split("a1b22c", A, /[0-9]+/)    ->  3: "a", "b", "c"
        split("a.b.c",  A, ".")         ->  3: "a", "b", "c"
        split("abc",    A, "")          ->  3: "a", "b", "c"

    An empty record has no fields under any separator, so NF is 0 and
    split() returns 0.

.NUMBER FORMATTING
    A value that is INTEGRAL always converts as an integer, and neither
    OFMT nor CONVFMT applies to it. There is no magnitude cutoff:

        print 1e17          ->  100000000000000000
        print 2^53          ->  9007199254740992

    A non-integral value uses OFMT in `print` and CONVFMT everywhere
    else -- concatenation, array subscripts, comparison against a
    string. Both default to "%.6g".

        BEGIN { OFMT="%.2f"; CONVFMT="%.4f"; x = 3.14159
                print x         # 3.14     (OFMT)
                print x ""      # 3.1416   (CONVFMT)
        }

    Going the other way, a STRING becomes a number by reading a leading
    decimal number and stopping. POSIX awk does not accept the hex,
    infinity or nan spellings that C's strtod does:

        "0x10" + 0  ->  0        (the number is 0; "x10" is trailing junk)
        "inf"  + 0  ->  0
        "12abc"+ 0  ->  12
        "1e3"  + 0  ->  1000

Examples

    awk '{ print $2 }' file.txt
        Print the second whitespace-separated field of each line.

    awk -F, '{ print $1, $3 }' data.csv
        Print the first and third columns of a CSV file.

    awk '/ERROR/ { print NR, $0 }' log.txt
        Print line number and content for every line containing ERROR.

    awk 'BEGIN { sum = 0 } { sum += $1 } END { print sum }' nums.txt
        Sum the first column.

    awk 'NR == 1 { next } { print }' file.txt
        Skip the header row.

    awk '{ count[$1]++ } END { for (k in count) print k, count[k] }' words.txt
        Frequency table of the first column.

    awk -F: '$3 >= 1000' /etc/passwd
        Lines (entire record) where the third colon-separated field is >= 1000.
        (Bare expression as pattern, no action: defaults to { print }.)

    awk 'length($0) > 80' file.txt
        Print lines longer than 80 characters.

    awk 'BEGIN { OFS = "\t" } { print $2, $1 }' file.txt
        Swap first two fields, output tab-separated.

    awk -v threshold=100 '$1 > threshold' nums.txt
        Filter using a command-line variable.

    type access.log | awk '{ ip[$1]++ } END { for (i in ip) print ip[i], i }' | sort -rn
        Top requesting IPs from a web log.

    awk 'function f(a,b,  t) { t = a + b; return t * 2 }
         BEGIN { print f(3, 4) }'
        A user-defined function. `t` is a LOCAL, because it is a
        parameter the caller does not supply.

    awk 'BEGIN { n = split("a1b22c", A, /[0-9]+/); print n, A[2] }'
        Split on a regex. Prints "3 b".

    awk 'BEGIN { system("cmd", "dir /w") }'
        Run a command through cmd.exe rather than through cshw.

    awk '{ print > ($1 ".txt") } END { for (f in seen) close(f) }'
        Fan a file out into per-key files, closing each when done so
        the handles are released.

    awk 'FNR == 1 { print FILENAME; nextfile }' *.log
        Print the first line of every file and skip the rest of each.

    awk 'BEGIN { for (i = 1; i < ARGC; i++) print "input:", ARGV[i] }' a b
        Walk the operands the program was given.

Exit status

0       Successful completion.
1       At least one input file could not be opened.
2       awk program syntax error.
N       The exit N statement exited with status N.

Notes

Regex flavor: cshw's awk uses PCRE2 (Perl Compatible Regular Expressions). Anything you'd expect from `awk` plus features like lookahead / lookbehind, named groups, and Unicode classes all work.

PCRE2 runs with Unicode properties on, so [[:alpha:]], [[:upper:]]
and [[:lower:]] match accented and non-Latin letters as POSIX says
they should in a UTF-8 locale. Two classes are held to ASCII
deliberately, because that is what awk means by them and what a
program guarding arithmetic with /^[[:digit:]]+$/ is relying on:
[[:digit:]]     0-9 only. A fullwidth or Devanagari digit is
[[:xdigit:]]    not [[:digit:]], though it is [[:alnum:]].
Word boundaries follow awk, not Perl:
\b      BACKSPACE, as in POSIX awk -- NOT a word boundary.
\y      The word boundary (gawk's spelling).
\<  \>  Start and end of a word.
\B      Not a word boundary.

Field separator: The default FS = " " is special: it splits on runs of any whitespace (spaces and tabs) AND trims leading/trailing whitespace from the record before splitting. Any other FS value is used literally; multi-character FS is treated as a regex.

Numeric vs string comparison: awk types are dynamic. A value compares numerically if both operands look numeric (a numeric literal, or a string that fully parses as a number), otherwise comparison is lexicographic. To force string comparison, concatenate with the empty string: if (a "" == b "") # always string compare

User-defined functions: function name(arg1, arg2, local1, local2) { body }

Defined at the top level, alongside the pattern-action rules, and
callable from anywhere in the program -- including from a line
ABOVE the definition, which is what mutually recursive helpers
need. `return expr` yields a value; a bare `return`, or falling
off the end, yields the uninitialized value ("" or 0).
awk has no local declarations. The SURPLUS PARAMETERS are the
locals: call with fewer arguments than the function names and the
rest arrive uninitialized. The extra spaces conventionally written
before them are a note to the reader and nothing to the parser.
Scalars are passed by VALUE and arrays by REFERENCE, decided by
what the variable already holds rather than by the call site:
function bump(n, A) { n = 99; A["k"] = "set" }
BEGIN { x = 1; bump(x, arr); print x, arr["k"] }   # 1 set
An argument that is still uninitialized has no type yet. If the
function subscripts it, the caller gets the array back; if the
function assigns it as a scalar, the caller is untouched.
A call requires the '(' hard against the name. With a space
between, `s (x)` is CONCATENATION of a variable and a parenthesized
expression -- the idiom behind every string-building loop in awk.
Built-in names may still be written with a space, as POSIX allows,
which is unambiguous because no user function may take one.
Recursion is supported to a depth of 1000 frames, which is far
more than real programs use -- a descent over a million sorted
items is 20 levels deep. Beyond it, awk reports "call depth
exceeded" rather than overrunning the stack.

Deliberate differences from GNU awk: These are choices, not gaps. Each was measured against GNU Awk 5.0.0 and settled in favour of POSIX.

* \& and \\ in a sub()/gsub() replacement follow POSIX: \&
  inserts a literal &, and \\ a literal backslash. gawk warns
  about the first and keeps both characters for the second.
* printf with fewer arguments than conversions treats the missing
  ones as "" and 0, which is what the original awk does. gawk
  makes it a fatal error.
* ARGV[0] is "awk", which POSIX specifies. gawk puts its own name
  there.
* The command forms of getline do not move NR. That follows GNU
  and diverges from the POSIX table, because matching the standard
  would disagree with every script written against gawk.

Unreadable input: An input file that cannot be opened stops the run: awk reports it, skips END, and exits 2 -- so a script cannot mistake a partial pass over its operands for a complete one. This follows gawk. The way to carry on regardless is the one gawk provides, a BEGINFILE rule that reads ERRNO:

awk 'BEGINFILE { if (ERRNO != "") nextfile }
     { ...work... }' *.log

Children and where their output goes: A child started by `print | "cmd"` writes to awk's own stdout when that is a terminal or a file, so its output appears live, interleaved with awk's.

When awk's stdout is a PIPE it cannot: cshw's builtins hand each
other UTF-16 while a child writes plain bytes, and a stream carrying
both is readable as neither. So in a pipeline the child's output is
collected and re-emitted through awk's own writer, which puts one
encoder in front of everything that leaves the process.
The visible consequence is WHEN it appears, not whether. Collected
output is written at close time:
print "x" | "sort"     # nothing yet
close("sort")          # sort's output appears here
With close() the ordering is exactly what the program says, in every
destination. Without it, a pipeline defers the child's output to the
end of the run. To a terminal, output from a child that was never
closed has always been timing-dependent -- it is a separate process
and may not finish before awk does. close() is the answer in every
awk, and this is what it is for.
system() and `"cmd" | getline` are unaffected either way.

Encoding: Input files are read as UTF-8 (with optional BOM stripped) and treated as wide-character internally. Programs that treat input as bytes (e.g. via length() on a multi-byte sequence) get character counts, not byte counts.

See also

sed, grep, cut, sort, uniq, type

barrier back to top ↑

rendezvous barrier for N participants

Synopsis

    barrier <name> create <count>
    barrier <name> wait [/timeout:ms]
    barrier <name> reset
    barrier <name> status
    barrier <name> destroy

Description

A named barrier that releases all participants at once when <count> of them have called wait -- a rendezvous point for a fan-out of coroutines. Create it with the participant count before use; waiting on an unknown name is an error.

Options

    create <count>      Create a barrier for count participants.
    wait [/timeout:ms]  Block until all arrive; $? = 0 passed, 1 timeout.
    reset               Reset for reuse.
    status              Show waiting count and total.
    destroy             Remove the barrier.

ON FAILURE
`wait` is FATAL. A barrier's whole guarantee is "nobody proceeds until everybody
arrives"; timing out and continuing does not weaken that guarantee, it deletes
it, and does so for the one participant that then races ahead of a cohort still
waiting behind it. There is deliberately no `trywait`: arriving at a barrier and
then leaving corrupts the count for everyone else, so the honest options are to
wait or to stop.

Examples

    barrier start create 3
    corunproc phase1 ; corunproc phase2 ; corunproc phase3
    # each worker calls: barrier start wait   (all resume together)

Exit status

0       Operation succeeded (wait: barrier passed).
>0      Wait timeout, unknown name, or bad usage.

See also

mutex, semaphore, event, channel, sync, corunproc

base back to top ↑

print a number in another radix

Synopsis

    base RADIX NUMBER...

Description

Prints each NUMBER in RADIX, which may be 2 through 36.

cshw reads numbers in several radices -- `@ x = 0x100` is 256 here, where tcsh answers "Badly formed number" -- and `base` is the other half of that: a way to write them back out.

NUMBER is read in the shell's usual conventions: plain decimal, or a `0x`, `0b` or `0o` prefix, with an optional sign. The same forms `@` accepts.

Options

    RADIX           The output radix, 2 to 36. Digits above 9 are A-Z.
    NUMBER          One or more integers to convert.

Round Trip

Output for radix 2, 8 and 16 carries the prefix that reads back as the same
number, so the pair is closed:

    set h = `base 16 48879`     # 0xBEEF
    @ back = $h                 # 48879

Other radices have no conventional prefix and are printed bare, so `base 36
48879` is `11PR` and a reader has to be told the radix -- which is true of
base 36 everywhere, not a limitation of this command.

Notes

A LEADING ZERO IS NOT OCTAL. `010` is ten, both here and in tcsh -- csh arithmetic is plain base 10, and C's rule does not apply. Write `0o10` for eight. This matters because zero-padded numbers are ordinary in scripts (dates, times, counters), and reading them as octal would silently change what they mean.

An integer whose digits do not belong to its prefix -- `0b12`, `0xZZ` -- is an error rather than a truncated value.

Examples

    base 10 0x100
        256

    base 16 255
        0xFF

    base 2 11
        0b1011

    base 8 64
        0o100

    base 36 1295
        ZZ

    base 16 48879 -255
        0xBEEF
        -0xFF

Exit status

0       All numbers converted.
1       A radix outside 2-36, or an operand that is not an integer.
        The operand is named; it is not silently skipped.

See also

@, bc, dc, seq, printf

base64 back to top ↑

encode or decode base64 data

Synopsis

    base64 [options] [FILE]
    base64 -s TEXT
    command | base64 [options]

Description

Encodes binary data to base64 text or decodes base64 text back to binary. Base64 is commonly used for encoding binary data in text-based formats like JSON, XML, email attachments, and data URIs.

The operand is a FILE, not a string: `base64 notes.txt` encodes the contents of notes.txt. To encode literal text, use -s, or pipe it in. With no file and no -s, base64 reads standard input.

Options

    FILE            File to encode/decode. Same as -i FILE.

    -e, --encode    Encode (the default).
    -d, --decode    Decode base64 input to binary output.
    -i, --input FILE
                    Read input from FILE.
    -o, --output FILE
                    Write output to FILE instead of standard output.
    -s, --string TEXT
                    Encode the literal TEXT (UTF-8) rather than a file.
    -w N            Wrap encoded lines at N characters (default: 76,
                    0 for no wrap).

    An unrecognized option is an error, not a silent no-op.

Examples

    base64 image.png
        Encode image.png to base64.

    base64 -d encoded.txt > decoded.bin
        Decode a base64 file to binary.

    base64 -s "Hello World"
        Encode literal text.

    echo "Hello World" | base64
        Encode text arriving on stdin.

    echo "SGVsbG8gV29ybGQ=" | base64 -d
        Decode base64 text.

    base64 -w 0 file.bin
        Encode without line wrapping.

    base64 -e -i binary.exe -o encoded.txt
    base64 -d -i encoded.txt -o decoded.bin
        Round-trip through files without touching the pipeline.

Exit status

0       Success
1       Input was not valid base64 (decode mode), the file could
        not be opened or written, or an option was unrecognized

Notes

Character Set: Base64 uses A-Z, a-z, 0-9, +, / and = for padding. URL-safe base64 uses - and _ instead of + and /.

Decoding is checked: Input that is not valid base64 is refused rather than decoded to whatever the bytes happened to mean.

Size Increase: Base64 encoding increases data size by approximately 33%.

Binary Safety: Base64 ensures binary data can be safely transmitted through text-only channels.

Common Uses: - Embedding images in HTML/CSS (data URIs) - Encoding credentials for HTTP Basic Auth - Encoding binary data in JSON - Email attachments (MIME)

See also

hexdump, md5sum, sha256sum

basename back to top ↑

strip directory and suffix from a path

Synopsis

    basename <path> [suffix]

Description

Print <path> with any leading directory components removed. Both forward slashes and backslashes are recognized as path separators, and trailing separators are ignored.

If a second argument is given it is treated as a suffix: when the result ends with that suffix, the suffix is removed as well -- but only when doing so still leaves a non-empty name.

basename does not touch the filesystem; it is a pure text operation on the path you give it.

Examples

    basename /usr/lib/file.txt
        Prints: file.txt

    basename /usr/lib/file.txt .txt
        Prints: file

    basename C:\Tools\cshw\cshw.exe .exe
        Prints: cshw

    basename /usr/lib/
        Prints: lib  (the trailing slash is ignored)

Exit status

Zero on success. basename with no path argument is a usage error.

See also

dirname, realpath

bc back to top ↑

arbitrary-precision calculator language

Synopsis

    bc                              interactive REPL (reads from stdin)
    bc "EXPR_OR_PROGRAM"            run source from argv
    bc -e "EXPR" [-e "EXPR"...]     inline expression (repeatable)
    bc -f FILE [-f FILE...]         script from file (repeatable)
    bc -i                           force REPL even with redirected stdin
    bc -l                           silently accepted (lib always loads)
    bc -x | --exact                 exact rational + Power arithmetic
    bc -c | --complex               complex-number arithmetic
    bc --lex   "SRC"                debug: dump token stream
    bc --parse "SRC"                debug: dump AST tree

Description

bc is the POSIX arbitrary-precision calculator language. cshw's implementation uses Gavin Howard's BCL (BSD 2-clause) for the arithmetic backend and a hand-written lexer, parser, and tree-walking interpreter for the language surface.

Numbers are arbitrary-precision decimal -- no float-format loss, no silent overflow. The current `scale` variable controls how many fractional digits division and the math library produce; `ibase` and `obase` control the input and output bases. Defaults: scale=20, ibase=10, obase=10.

bc is a real little programming language: statements, expressions, variables, sparse arrays, user-defined functions with `auto` locals, recursion, control flow (if / else / while / for, with break and continue), and a standard math library (loaded automatically).

Language

Expression operators, low to high precedence:

    = += -= *= /= %= ^=     assignment (right-associative)
    || &&                   short-circuit logical
    < <= == != >= >         relational
    + -                     additive
    * / %                   multiplicative
    -                       unary minus (binds LESS tight than ^)
    ^                       power (right-associative)
    ! ++ --                 logical-not, prefix increment/decrement
    ++ --                   postfix increment/decrement
    primaries               NUMBER, NAME, NAME[expr], NAME(args),
                            (expr), built-in calls

Numbers may use digits 0-9 plus A-Z when ibase > 10 (A=10, B=11, ...).
A standalone uppercase letter is always its constant value (so
`ibase=A` is the canonical idiom for "set base 10 regardless of
current base").

Statements: blocks { ... }, if (cond) stmt [else stmt],
while (cond) stmt, for (init; cond; step) stmt, break, continue,
halt, quit, return [VALUE], print ITEM [, ITEM...], define
[void] NAME(PARAMS) { [auto LOCALS;] BODY }. A bare expression
statement prints its value and updates `last` (unless inside a
function body).

Comments: /* block */ and # to end-of-line. Backslash-newline is
line continuation inside numbers.

.MATH LIBRARY
Loaded automatically. POSIX names:
    e(x)        e^x
    l(x)        natural log
    s(x)        sine
    c(x)        cosine
    a(x)        arctangent
    j(n, x)     Bessel function of the first kind, order n

cshw friendly aliases:
    sin(x) cos(x) tan(x)
    asin/acos/atan via a()
    atan2(y, x)
    exp(x) ln(x)
    log(x) log10(x) log2(x)
    pi()

Examples

    bc "1 + 2 * 3"                                  -> 7
    bc -e "scale=50; 1/3"                           -> .3333... (50 digits)
    bc -f myscript.bc                               run a script file
    bc "define f(n){if(n<2)return n; return f(n-1)+f(n-2)}; f(20)"
                                                    -> 6765 (recursive fib)
    bc "for(i=1;i<=10;i++) i*i"                     -> 1 4 9 16 ... 100
    bc "pi()"                                       -> 3.14159...
    bc "sin(pi()/2)"                                -> 1.000...
    bc                                              drop into interactive REPL

.EXACT MODE (-x, --exact)
With `-x` / `--exact`, integer literals stay integer and rational
arithmetic preserves p/q form: `bc -x "1/3 + 1/6"` prints `1/2`, not
`.4999...` truncated. Plus a Power(rational, rational) layer carries
sqrt and powers symbolically:

    bc -x "1/3 + 1/6"           -> 1/2
    bc -x "5/15"                -> 1/3       (auto-reduced)
    bc -x "2^10"                -> 1024      (integer fold)
    bc -x "(1/2)^2"             -> 1/4
    bc -x "sqrt(2)"             -> 2^(1/2)   (symbolic)
    bc -x "sqrt(2) * sqrt(2)"   -> 2         (same-base fold)
    bc -x "x = 1/3; y = 1/6; x+y"               -> 1/2  (variables work)

Operations that preserve form stay exact; anything else falls through
to BCL's scaled-decimal. This is NOT a CAS:

    bc -x "sqrt(2) + sqrt(3)"   -> 3.14626436...   (no symbolic sum)
    bc -x "sin(1)"              -> .84147098...    (transcendentals)

The contract is "exact when possible," not "always exact."

.EXACT-MATRIX TIER (1.0.6.4)
Within `-x` mode, bc also handles small matrices of exact rationals.
Matrix literals use bracketed-list syntax `[[a, b], [c, d]]`; arithmetic
+ - * works between matrices (with dimension checks); scalar * matrix and
matrix * scalar broadcast a Rational across all entries; matrix / scalar
divides by a Rational. Built-in functions:

    det(M)              determinant (M must be square)
    transpose(M)        the obvious thing
    inverse(M)          via Gauss-Jordan elimination over rationals
                        (M must be square and non-singular)
    mget(M, i, j)       element at row i, col j (0-indexed)
    mset(M, i, j, v)    return a new matrix with entry (i,j) replaced
    rows(M) / cols(M)   dimensions

Examples:

    bc -x "[[1, 2], [3, 4]] * [[5, 6], [7, 8]]"        -> [[19, 22], [43, 50]]
    bc -x "det([[6, 1, 1], [4, -2, 5], [2, 8, 7]])"    -> -306
    bc -x "inverse([[4, 7], [2, 6]])"                  -> [[3/5, -7/10], [-1/5, 2/5]]
    bc -x "m = [[1, 2], [3, 4]]; m * inverse(m)"       -> [[1, 0], [0, 1]]

The entries stay exact rational through every step -- inverse() produces
a rational matrix whose entries are arbitrary p/q. There is no numerical
linear algebra (no LU/QR/SVD, no eigenvalues). This is "symbolic exact
linear algebra for small matrices", not a NumPy replacement. For matrices
larger than about 6x6, the cofactor-expansion determinant slows down;
for floating-point matrix work, shell out to Python or MATLAB.

Gotchas

- Variable names: bc inherits BCL's base-36 number parsing, so uppercase
  single letters A-Z lex as numbers (M = 22, T = 29, I = 18, etc.). Use
  lowercase identifiers for matrix variables: `m = [[...]]` works,
  `M = [[...]]` does not (M is parsed as the literal 22). Same gotcha
  applies to complex-mode imaginary literals (use `cplx(0, 1)`, not `I`).
- Matrix literals are only valid in `-x` mode. Outside `-x`, attempting
  one raises a runtime error.

.COMPLEX MODE (-c, --complex)
With `-c` / `--complex`, bc gains complex-number arithmetic via four
lowercase built-ins: `cplx(re, im)` constructs `re + im*i`, `re(z)`
and `im(z)` extract the real and imaginary parts, `conj(z)` returns
the conjugate, and `abs(z)` returns the magnitude. The imaginary
unit is `cplx(0, 1)` (lowercase function names dodge BCL's base-36
number parsing -- `I` would lex as 18, not an identifier).

    bc -c "cplx(0, 1) * cplx(0, 1)"        -> -1
    bc -c "cplx(1, 2) + cplx(3, 4)"        -> 4+6i
    bc -c "cplx(3, 4) * cplx(1, 2)"        -> -5+10i
    bc -c "(cplx(1, 1)) / cplx(1, -1)"     -> i
    bc -c "sqrt(cplx(-4, 0))"              -> 2i
    bc -c "abs(cplx(3, 4))"                -> 5
    bc -c "conj(cplx(3, 4))"               -> 3-4i

Equality (`==` / `!=`) is defined structurally on complex values.
Ordering (`<` / `>` / `<=` / `>=`) raises a runtime error -- complex
numbers have no total order. `-c` composes with `-x`: real and imag
parts are decimal even in `-x -c`, but rational-only arithmetic on
real inputs stays exact as usual.

Output format: `a+bi` with the obvious shortcuts -- the zero terms
are dropped (`5i` not `0+5i`), unit coefficients omit the `1` (`3+i`
not `3+1i`), and negative imaginary parts use `-` not `+-` (`3-4i`).

Repl

With no inline source and a TTY stdin, bc enters an interactive REPL
showing `bc> ` for new statements and `... ` for continuation lines.
Multi-line definitions accumulate until braces balance. Use `quit`
or `halt` to return to cshw. `-x` and `-c` apply to the REPL too.

.SEE ALSO
    dc(1)               the RPN sibling
    @ (cshw builtin)    inline csh arithmetic with float primitives

Notes

Implementation: BCL (Gavin Howard's bc, BSD 2-clause) for arithmetic backend; cshw-written lexer / parser / interpreter for the language. The math library is a verbatim copy of Gavin's lib.bc; the alias layer (sin, cos, pi, ...) is cshw's own.

bg back to top ↑

move job to background

Synopsis

    bg [%JOBID]

Description

Resumes a stopped job and runs it in the background. If no job ID is specified, operates on the current job.

Resuming a job that is ALREADY running succeeds and does nothing, the same way `stop` on an already-stopped job does. It used to report "could not resume job N" at status 1.

Options

    %JOBID          Job number (from jobs command).

Examples

    bg
        Resume current job in background.

    bg %1
        Resume job 1 in background.

    # Common workflow:
    longcommand
    # Press Ctrl+Z to stop
    bg
        # Now it runs in background

Exit status

0       Success
1       No such job
2       Job cannot be backgrounded

Notes

Typical Workflow: 1. Start a command 2. Press Ctrl+Z to suspend it 3. Type 'bg' to continue in background 4. Use 'fg' later to bring back to foreground

Output: Backgrounded processes may still produce output to the terminal. Consider redirecting output when backgrounding.

See also

fg, jobs, kill, stop

bindevent back to top ↑

bind a script proc as a window event handler

Synopsis

    bindevent <hwnd> <kind> [<args>] <procname>

Description

Records a script-proc handler for a Win32 message on a given window. Whitelisted messages are routed through CSHW's dispatcher; on the next matching event, the bound proc runs.

All handlers except `close` fire as coroutines (off the UI thread, so the UI stays responsive). `close` handlers run synchronously on the UI thread -- returning a truthy $result vetoes the close.

`$hwnd` is set to the originating window for the handler's duration.

Options

    <hwnd>      Target HWND in hex or decimal. Must satisfy IsWindow().
    <kind>      One of:
                  command <ctlId>      WM_COMMAND from <ctlId>
                                       $1=ctlId  $2=notifyCode
                  notify  <ctlId>      WM_NOTIFY  from <ctlId>
                                       $1=ctlId  $2=notifyCode
                  timer   <timerId>    WM_TIMER
                                       $1=timerId
                  close                WM_CLOSE  (SYNCHRONOUS, $result vetoes)
                  destroy              WM_DESTROY
                  lbuttondown          WM_LBUTTONDOWN  $1=x $2=y
                  lbuttonup            WM_LBUTTONUP    $1=x $2=y
                  keydown <vk>         WM_KEYDOWN      $1=vk
                  size                 WM_SIZE         $1=width $2=height
    <procname>  Proc to invoke. Must already be defined via `proc`.

Examples

    proc on_ok
        echo "OK clicked"
    endproc
    bindevent $w command 100 on_ok

    proc veto_close
        share user_clicked_x = 1
        return 1            # veto -- window stays open
    endproc
    bindevent $w close veto_close

    proc on_size
        echo "resized to ${1}x${2}"
    endproc
    bindevent $w size on_size

Exit status

0       Binding installed.
1       Bad HWND, unknown kind, missing args, or undefined proc.

Notes

WM_CLOSE handlers run synchronously on the UI thread. Slow handlers stall the UI; do not call dialog APIs (passworddlg, messagebox, etc.) from a close handler -- it deadlocks.

For windows NOT created by `createwindow` (e.g., one returned by a future `findwindow`, or a plugin-class window), CSHW installs a SetWindowSubclass shim on first bind so the binding actually receives messages.

See also

unbindevent, createwindow, addcontrol, sendmessage, postmessage

bugreport back to top ↑

compose and send a bug report to bugs@tropibyte.com

Synopsis

    bugreport
    bugreport "subject"
    bugreport "subject" "details"

Description

Open a bug-report email composed in your default mail client, addressed to bugs@tropibyte.com. With no arguments, presents a modal dialog to collect a subject line and free-text details. With one or two string arguments, skips the dialog and goes straight to the mail client.

Nothing is sent until you click Send. cshw only opens the composer -- you remain in control of the final message.

By default, three diagnostic lines are appended to the body: - cshw version (from the binary's VS_VERSION_INFO resource) - Windows version + build number - Last shell error code, if any

The dialog has a checkbox to suppress those. The two- and three-argument forms always include them.

Arguments

    "subject"
        Short summary of the bug. Used as the email Subject line, with
        "cshw bug: " prepended.
    "details"
        Free-text body. Multi-line OK. Pre-formatted; mail clients
        respect the line breaks.

Examples

    bugreport
        Open the modal dialog.

    bugreport "foreach hangs on empty list"
        Compose with just a subject. Body will contain only the
        diagnostics tail.

    bugreport "sed -i fails" "sed -i s/a/b/ file.txt returns error 5"
        Subject + body, no dialog.

Exit status

0       Mail client opened successfully.
1       Dialog cancelled, or ShellExecute failed.

Notes

The mail client is selected by the system's default mailto: handler -- typically Outlook, Thunderbird, the Windows Mail app, or a webmail handler that registered itself. If no handler is registered, the command fails with a hint pointing at bugs@tropibyte.com directly.

The web equivalent (no cshw installed) is https://tropibyte.com/bugs.html which presents the same fill-in-the-blanks mailto: template.

See also

version, ver, about

cancel back to top ↑

remove jobs from a print queue (System V spelling of lprm)

Synopsis

    cancel [-d PRINTER] JOBID...
    cancel [-d PRINTER] -a

Description

The System V name for lprm. They are the SAME command in cshw, with the same options and behaviour; both accept -d and -P.

See lprm(1) for the full description.

Examples

    cancel 17
    cancel -a
    cancel -d "Front Desk" 12 13

Exit status

0       Every named job was removed
1       At least one could not be

See also

lprm, lpq, lpc, lp, lpr

cat back to top ↑

concatenate file(s) (or stdin) to standard output

Synopsis

    cat [options] [file...]
    cat [options] - [file...]
    command | cat [options]

Description

Concatenates one or more files (or standard input) to standard output. With no file argument, or when file is '-', cat reads from standard input.

cshw's cat folds together the GNU coreutils, BSD, AIX, and Solaris feature sets so users moving between shells keep their muscle memory. Long-form (--number), short-form (-n), and cshw-style (/n) switches are all accepted.

cat is encoding-aware on input: UTF-16 LE/BE and UTF-8 BOMs are detected and decoded automatically; otherwise input is read as the active code page.

Options

    -n  --number               Number all output lines, right-justified in 6
                               columns followed by a TAB.
    -b  --number-nonblank      Number non-empty lines only. Overrides -n.
    -s  --squeeze-blank        Collapse runs of consecutive blank lines into
                               a single blank line.
    -E  --show-ends            Print '$' at the end of each line.
    -T  --show-tabs            Print TAB characters as '^I'.
    -v  --show-nonprinting     Print control characters and high-bit bytes
                               using ^X / M-X notation. LF and TAB are not
                               affected unless -E or -T is also given.
    -A  --show-all             Equivalent to -vET.
    -e                         Equivalent to -vE.
    -t                         Equivalent to -vT.
    -q  --quiet                Silent on missing files (AIX behavior).
    -u                         Accepted for POSIX compatibility (no-op:
                               cshw's stdout is line-buffered already).
    -                          Read standard input at this position.
    --                         End of options; remaining tokens are files.

Examples

    cat file.txt
        Print the file to stdout.

    cat file1.txt file2.txt > combined.txt
        Concatenate two files into a third via redirection.

    cat -n script.cshw
        Number every line.

    cat -b notes.md
        Number only non-blank lines.

    cat -s log.txt
        Squeeze consecutive blank lines so the output is denser.

    cat -A weird.txt
        Reveal all non-printing structure: tabs as ^I, line ends as $,
        control bytes as ^X / M-X.

    ls | cat -n
        Number a piped stream.

    cat - file.txt
        Read from stdin first, then file.txt.

    cat -q maybe_missing.txt always_present.txt
        Don't error if maybe_missing.txt isn't there (AIX-style).

Exit status

0       Success
>0      One or more files could not be read (unless -q was given)

Notes

Encoding: Input files with a UTF-16 LE BOM, UTF-16 BE BOM, or UTF-8 BOM are decoded into wide characters. Files without a BOM are interpreted as the active code page (CP_ACP). The output stream is wide-aware so redirection and piping preserve characters.

Stream order: Files are emitted in the order given on the command line. With -n or -b, line numbers continue across file boundaries (one logical concatenated stream), matching standard cat behavior.

-s with non-empty lines: -s only collapses fully empty lines (or CR-only lines). It does not strip whitespace from non-empty lines.

Difference from type: 'type' is cshw's DOS-style file-display command and takes no options. 'cat' is the Unix-style equivalent with the full option surface above.

See also

type, head, tail, grep, wc, awk

cd back to top ↑

change the current working directory

Synopsis

    cd [directory]
    cd [options]
    chdir [directory]

Description

Aliases: chdir

Changes the shell's current working directory. If no directory is specified, displays the current directory path. The cd command supports both absolute and relative paths, as well as several special keywords.

When changing to a new directory, CSHW maintains a per-drive directory cache, allowing you to return to the last directory on each drive by specifying just the drive letter.

The cd command also integrates with the shell's alias system, so you can create shortcuts to frequently accessed directories.

Options

    directory       The path to change to. Can be absolute or relative.

    Special values:
    -               Change to the previous directory (like UNIX cd -)
    ~               Change to the user's home directory (%USERPROFILE%)
    ..              Change to the parent directory
    ...             Change to the grandparent directory (two levels up)
    ....            Change to three levels up (and so on)
    system          Change to %SystemRoot% (usually C:\Windows)
    windows         Change to %SystemRoot% (usually C:\Windows)

    Drive letters:
    D:              Change to drive D: and restore the last directory on that drive

Examples

    cd
        Display the current working directory.

    cd C:\Users\Public
        Change to an absolute path.

    cd ..
        Change to the parent directory.

    cd ...
        Change up two directory levels.

    cd ~
        Change to your home directory (%USERPROFILE%).

    cd -
        Return to the previous working directory.

    cd system
        Change to the Windows system directory (C:\Windows).

    cd D:
        Switch to drive D: and restore the last working directory on that drive.

    cd "Program Files"
        Change to a directory with spaces in the name (quoted).

Exit status

0       Success - directory was changed
1       Directory not found
2       Invalid argument or syntax error

Environment

USERPROFILE     Used when cd ~ is invoked
SystemRoot      Used when cd system or cd windows is invoked

Notes

$cdpath: When a bare relative name is not in the current directory, cd looks for it under each directory in $cdpath:

set cdpath = (~/projects /usr/local/src)
cd myapp            # finds ~/projects/myapp

cd prints the directory when cdpath is what found it, so it is visible that `cd myapp` did not mean ./myapp. A name that says where to look -- absolute, or starting with . or .. -- is taken at its word and does not consult cdpath. $cdpath was accepted and ignored before: cd reported "file not found" and, worse, left the shell where it was, so a script that carried on with relative paths operated on the wrong directory.

CSHW maintains a separate current directory for each drive letter. When you switch drives using just the drive letter (e.g., cd D:), the shell restores your previous position on that drive.

The command 'chdir' is an alias for 'cd' and works identically.

Unlike cmd.exe, CSHW's cd command supports the UNIX-style cd - to return to the previous directory.

See also

pushd, popd, pwd, dirs

chancreate back to top ↑

create a message-passing channel (shorthand)

Synopsis

    chancreate <name> [capacity]

Description

Shorthand for `channel <name> create [capacity]`. capacity 0 (or omitted) creates an unbounded channel where send never blocks. Use the channel command for send/receive/close/status/destroy.

Examples

    chancreate results          # unbounded
    chancreate work 16          # bounded to 16 buffered messages

Exit status

0       Created.
>0      Bad usage.

See also

channel, semcreate

channel back to top ↑

message-passing channel between coroutines

Synopsis

    channel <name> create [capacity]
    channel <name> send <message>
    channel <name> receive [/timeout:ms]
    channel <name> tryreceive
    channel <name> close
    channel <name> status
    channel <name> destroy
    channel <operation> <name> [args]     (either order works)

Description

A named CSP-style channel carrying string messages between coroutines and threads. capacity 0 (or omitted) is unbounded (send never blocks); a bounded channel blocks send when full. receive and tryreceive set $result to the message. send fails on a closed channel. Create before send/receive; either `channel <name> <op>` or `channel <op> <name>` order is accepted.

Options

    create [capacity]      Create the channel (0 = unbounded).
    send <message>         Enqueue a message (remaining words are joined).
    receive [/timeout:ms]  Dequeue, blocking; sets $result; $? = 0 got, 1 timeout/closed.
    tryreceive             Non-blocking dequeue; sets $result; $? = 0 got, 1 empty.
    close                  Close for sending (receivers still drain the buffer).
    status                 Show count, capacity, and closed state.
    destroy                Remove the channel.

EXIT STATUS OF receive
    0   a message was received; it is in $result
    1   end of stream -- the channel is closed and drained
    2   timed out waiting; the channel is still open and more may arrive

1 and 2 used to be the same answer, so a consumer could not tell "we are done"
from "I gave up waiting" and a slow producer looked exactly like a finished one.
Both are non-zero, so the usual drain loop is unaffected:

    while (1)
        channel c receive
        if ($status != 0) break
        ...
    end

`receive` is deliberately NOT fatal, unlike `semaphore acquire` or `event wait`:
reaching the end of a channel is a normal outcome, not a failure.

Examples

    chancreate work 10          # == channel work create 10
    channel work send "task-1"
    channel work receive
    echo $result

Exit status

0       Operation succeeded (receive: got a message).
>0      Receive timeout/empty, send on closed, unknown name, or bad usage.

See also

chancreate, semaphore, mutex, event, barrier, sync, corunproc

chdir back to top ↑

change the current working directory (alias for cd)

Synopsis

    chdir [directory]

Description

`chdir` is identical to `cd`. See `man cd` for full documentation, options, and examples.

See also

cd, pwd, pushd, popd

checkmail back to top ↑

check $mail now for new messages

Synopsis

    checkmail

Description

Forces the same new-mail check cshw runs automatically before each interactive prompt. The mailboxes and poll interval come from the $mail variable:

set mail = (interval path ...)

where a leading number is the poll interval in seconds (0 disables automatic checking) and each path is either a Maildir directory (new mail = a change in the count of *.eml files) or an mbox file (new mail = the file grew). When a mailbox has grown since the last check, checkmail prints "You have new mail for user: <name>".

Examples

    set mail = (60 ~/Maildir/new)
    checkmail

Exit status

0       Check performed (whether or not new mail was found).

See also

set, imap, pop3

chmod back to top ↑

change file permissions

Synopsis

    chmod MODE FILE
    chmod [options] MODE FILE...

Description

Changes file access using UNIX mode syntax, mapped onto the two things Windows actually checks: the read-only attribute and the NTFS access control list.

An OCTAL mode writes a real ACL, one entry per class -- owner, primary group, and Everyone for "other". r grants read, w grants write and delete, x grants FILE_EXECUTE. `chmod 700` really does exclude everyone but the owner, and `chmod 444` really does refuse a write.

A mode that withholds access from the owner is enforced with DENY entries. Windows grants the UNION of every matching ALLOW entry, and on a workgroup machine the owner is frequently also the primary group, so without them `chmod 466` -- owner read-only, other read-write -- would hand the owner write access straight back through Everyone.

A SYMBOLIC mode answers one question, may this file be written, and sets or clears the read-only attribute. Per-principal forms (u+w, o-r) are accepted but affect that same single question; reach for an octal mode when you need per-class control.

The two forms compose. Windows checks the attribute and the ACL independently and a write needs BOTH to permit it, so each form keeps the other in step: once an octal mode governs a file a later +w or -w edits the ACL, and an octal mode sets or clears read-only to match the owner's write bit. Without that, `chmod -w f` followed by `chmod 644 f` reported success twice and left the file unwritable.

THE EXECUTE BIT DOES NOT DECIDE WHAT RUNS. Windows decides that from the file extension and PATHEXT, so `chmod +x notes.txt` will not make notes.txt runnable -- no shell on Windows can make that true. It is not ignored either: x grants or withholds FILE_EXECUTE, so `chmod 644 tool.exe` will stop tool.exe from launching.

Options

    MODE            Permission mode (numeric or symbolic).
    FILE            File(s) to modify.

    Numeric mode (octal):
    400             Owner read
    200             Owner write
    100             Owner execute
    040             Group read
    020             Group write
    010             Group execute
    004             Others read
    002             Others write
    001             Others execute

    Symbolic mode:
    u               User (owner)
    g               Group
    o               Others
    a               All (ugo)
    +               Add permission
    -               Remove permission
    =               Set exact permission
    r               Read
    w               Write
    x               Execute

    Options:
    -R, --recursive Apply recursively.
    -v, --verbose   Verbose output.

Examples

    chmod 644 file.txt
        Owner read/write, others read-only.

    chmod 755 script.exe
        Owner full, others read/execute.

    chmod +x script.bat
        Add execute permission.

    chmod -w readonly.txt
        Remove write permission (make read-only).

    chmod u+w,go-w file.txt
        Owner writable, others not.

    chmod -R 755 directory/
        Recursively set permissions.

Exit status

0       Success
1       File not found
2       Access denied
3       Invalid mode

Notes

Windows Mapping: UNIX permissions don't map directly to Windows. chmod primarily: - Sets/clears read-only attribute (write permission) - Modifies NTFS ACLs where possible

Read-Only: The most common use is toggling read-only: chmod -w file.txt # Make read-only chmod +w file.txt # Make writable

Execute Permission: On Windows, execute permission is determined by file extension, not a permission bit. chmod +x has limited effect.

NTFS ACLs: For full Windows permission control, use icacls or the attrib command for attributes.

Scripts: chmod is useful for cross-platform scripts that expect UNIX permission syntax.

See also

chown, attrib, stat

chown back to top ↑

change file owner

Synopsis

    chown OWNER FILE
    chown OWNER:GROUP FILE
    chown [options] OWNER FILE...

Description

Changes the owner of files and directories. On Windows, this modifies the file's security descriptor to set a new owner.

Options

    OWNER           New owner (username or SID).
    GROUP           New group (optional, after colon).
    FILE            File(s) to modify.

    -R, --recursive Apply changes recursively to directories.
    -v, --verbose   Show files as they're processed.

Examples

    chown Administrator file.txt
        Change owner to Administrator.

    chown DOMAIN\User document.docx
        Change owner to domain user.

    chown -R Administrator C:\Data
        Recursively change owner of directory tree.

    chown "NT AUTHORITY\SYSTEM" service.exe
        Change owner to SYSTEM account.

Exit status

0       Success
1       File not found
2       Access denied (need Administrator)
3       Invalid owner

Notes

Administrator Required: Changing file ownership typically requires Administrator privileges or SeRestorePrivilege/SeTakeOwnershipPrivilege.

Taking Ownership: Administrators can take ownership of any file even if current permissions deny access.

Windows vs UNIX: - UNIX chown: Changes owner and optionally group - Windows: Owner is part of security descriptor, groups work differently

Security Descriptors: File ownership is part of Windows NTFS security. The owner has special privileges including the ability to modify permissions.

SIDs: You can specify owners by Security Identifier (SID) instead of name: chown S-1-5-18 file.txt # SYSTEM

See also

chmod, attrib, stat

clip back to top ↑

copy to clipboard

Synopsis

    clip < FILE
    command | clip
    clip [options]

Description

Copies text from standard input to the Windows clipboard. The copied content can then be pasted into any application.

Options

    Standard input is copied to clipboard.

    /p              Paste clipboard contents to stdout (read clipboard).

Examples

    dir | clip
        Copy directory listing to clipboard.

    type file.txt | clip
        Copy file contents to clipboard.

    echo "Hello" | clip
        Copy text to clipboard.

    clip /p
        Display current clipboard contents.

    clip /p > saved.txt
        Save clipboard to file.

    grep error log.txt | clip
        Copy matching lines to clipboard.

Exit status

0       Success
1       Clipboard access error

Notes

Text Only: clip works with text data. Binary data will be treated as text and may not produce expected results.

Unicode: Unicode text is supported and preserved.

Integration: clip is useful for copying command output to paste elsewhere: - Copy file paths for email - Copy command output for documentation - Copy error messages for searching

See also

type, echo

cls back to top ↑

clear the console screen

Synopsis

    cls [/scroll]

Description

Clears the console screen and moves the cursor to the home position (top-left corner).

By default, cls erases the entire console buffer including all scrollback history. The screen is completely cleared.

Options

    /scroll, /s, -scroll, -s
        Preserve scrollback buffer. Instead of erasing the buffer,
        content is scrolled up and filled with blank lines. You can
        still scroll back to see previous output.

Examples

    cls
        Clear the screen and erase all scrollback history.

    cls /scroll
        Clear the visible screen but preserve scrollback buffer.

    cls /s
        Same as cls /scroll.

Exit status

0       Success

Notes

Alternative Names: Some systems use 'clear' instead of 'cls'. CSHW supports both.

Windows 10+ Required: The default erase behavior uses VT100 escape sequences which require Windows 10 or later. On older systems, the behavior may fall back to scroll mode.

See also

echo, clear

cmdliblist back to top ↑

list loaded command libraries

Synopsis

    cmdliblist
    cmdliblist /verbose

Description

Displays information about all currently loaded command libraries. Shows library name, version, prefix, path, and command count.

With the /verbose option, also lists all commands provided by each library and indicates which ones shadow intrinsic commands.

Options

    /verbose    Show detailed command list for each library.
    /v          Short form of /verbose.

Examples

    cmdliblist
        List all loaded libraries with basic info.

    cmdliblist /v
        List libraries with all their commands.

Output

For each library, displays:
    - Library name (or path if no name)
    - Version (if specified by plugin)
    - Prefix and whether it's required
    - Full DLL path
    - Number of commands registered

With /verbose, also shows:
    - Each command name
    - Command description
    - Whether it shadows an intrinsic command

Exit status

0       Always succeeds

See also

rcl, urcl

cocancel back to top ↑

cancel a running coroutine

Synopsis

    cocancel <coid> | /all

Description

Requests cancellation of a running coroutine (or every coroutine with /all). Cancellation is cooperative: the coroutine stops at its next checkpoint, so a coroutine that never yields may not stop immediately.

Examples

    cocancel $coid
    cocancel /all

Exit status

0       Cancellation requested.
>0      Unknown coroutine id.

See also

corunproc, cowait, cosuspend, colist

cocas back to top ↑

atomic compare-and-swap on a thread-safe variable

Synopsis

    cocas <name> <expected> <newvalue>

Description

Atomically sets the atomic variable name to newvalue only if its current value equals expected (string comparison; an unset variable compares as ""). Sets $? to 0 if the swap happened, 1 if not -- the primitive for lock-free retry loops across coroutines.

Examples

    coset state idle
    cocas state idle busy       # $? = 0, state is now busy
    cocas state idle busy       # $? = 1, no change

Exit status

0       Swapped (current value matched expected).
1       Not swapped (mismatch).
>1      Bad usage.

See also

coincr, codecr, coset, coget

coclean back to top ↑

remove completed coroutines from tracking

Synopsis

    coclean

Description

Drops finished coroutines from the tracking table, freeing their ids and stored results. Read any results you still need with coresult first.

Examples

    wait
    coclean

Exit status

0       Always.

See also

colist, coresult, corunproc

codecr back to top ↑

atomically decrement a thread-safe variable

Synopsis

    codecr <name> [amount]

Description

Atomically subtracts amount (default 1) from the integer value of the atomic variable name (see coset), and stores the PREVIOUS value in $result -- a fetch-and-subtract. An unset variable is treated as 0.

Examples

    coset remaining 10
    codecr remaining    # $result = 10, remaining is now 9

Exit status

0       Decremented.
>0      Bad usage.

See also

coincr, coset, coget, cocas

coget back to top ↑

read a thread-safe atomic variable

Synopsis

    coget <name>

Description

Reads name from the atomic-variable table (see coset) and stores it in $result; an unset name yields the empty string. These atomic variables are distinct from ordinary `set` shell variables.

Examples

    coset total 0
    coincr total
    coget total
    echo $result

Exit status

0       Always (unset name gives "").

See also

coset, coincr, codecr, cocas

coincr back to top ↑

atomically increment a thread-safe variable

Synopsis

    coincr <name> [amount]

Description

Atomically adds amount (default 1) to the integer value of the atomic variable name (see coset), and stores the PREVIOUS value in $result -- a fetch-and-add. An unset variable is treated as 0. Safe to call concurrently from coroutines.

Examples

    coset n 0
    coincr n            # $result = 0, n is now 1
    coincr n 5          # $result = 1, n is now 6

Exit status

0       Incremented.
>0      Bad usage.

See also

codecr, coset, coget, cocas

colist back to top ↑

list coroutines and their status

Synopsis

    colist [/active] [/completed] [/all]

Description

Prints the tracked coroutines with their id and status (running, suspended, or completed). Filter with /active or /completed; /all (the default) shows both. Completed coroutines stay tracked until coclean removes them.

Examples

    colist
    colist /active

Exit status

0       Always.

See also

corunproc, cowait, coclean, coresult

complete back to top ↑

define tab completion rules

Synopsis

    complete COMMAND PATTERN
    complete COMMAND TYPE

Description

Defines custom tab completion rules for commands. When you press Tab after a command, the shell uses these rules to suggest completions.

Options

    COMMAND         Command to define completion for.
    PATTERN         Glob pattern for completions.
    TYPE            Completion type:
                    f   Files (default)
                    d   Directories only
                    c   Commands
                    e   Environment variables
                    a   Aliases
                    v   Variables

Examples

    complete cd d
        Complete cd with directories only.

    complete type f
        Complete type with files.

    complete kill p
        Complete kill with process IDs.

    complete set v
        Complete set with variable names.

    complete source "*.csh"
        Complete source with .csh files.

    complete git "(add|commit|push|pull|status)"
        Complete git with subcommands.

Exit status

0       Success
1       Invalid pattern

Notes

Tab Completion: When you type a command and press Tab, the shell: 1. Checks for 'complete' rules for that command 2. Uses the rule to filter/suggest completions for the current token 3. Inserts the next match inline when there is a single match (or a shared prefix) 4. Displays a list of matches when multiple results exist 5. Falls back to default (file) completion if no rule

Interactive Behavior: - Tab completes the current word at the cursor (end-of-line) - If multiple matches exist, the shell prints them and redraws the prompt - Completion types support files, directories, commands, aliases, variables, and environment variables

Default Behavior: Without custom rules, Tab completes filenames.

Multiple Arguments: Completion rules can vary by argument position: complete command (dir file file)

Listing Rules: Use 'complete' without arguments to list all defined completions.

See also

uncomplete, alias

copy back to top ↑

copy files

Synopsis

    copy SOURCE DESTINATION
    copy SOURCE... DIRECTORY

Description

Aliases: cp

Copies one or more files to a destination. If the destination is a directory, files are copied into that directory preserving their original names. If copying a single file to a non-directory destination, the file is copied with the new name.

The copy command uses the Windows CopyFile API, which preserves file attributes and handles large files efficiently.

Options

    SOURCE          The file(s) to copy. Wildcards (* and ?) are supported.

    DESTINATION     The target file or directory.

    /y              Suppress confirmation prompt when overwriting.

    /v              Verify that new files are written correctly.

Examples

    copy file.txt backup.txt
        Copy file.txt to backup.txt in the same directory.

    copy document.docx D:\Backup\
        Copy document.docx to the D:\Backup directory.

    copy *.txt TextFiles\
        Copy all .txt files to the TextFiles subdirectory.

    copy "My File.doc" "My Backup.doc"
        Copy a file with spaces in the name.

    copy src\*.cpp backup\src\
        Copy all C++ source files to a backup location.

Exit status

0       Success - all files copied
1       Source file not found
2       Destination access denied or disk full
3       Syntax error

Notes

Overwriting: If the destination file already exists, copy will overwrite it without prompting (use /y to explicitly suppress any prompts).

Large Files: The copy command handles files of any size, including files larger than 4GB.

Network Paths: UNC paths (\\server\share\file) are fully supported.

Preserving Attributes: File attributes (read-only, hidden, system, archive) are preserved during the copy operation.

See also

mv, del, rm, type

coresult back to top ↑

get the result of a completed coroutine

Synopsis

    coresult <coid>

Description

Reads the return value published by a finished coroutine (the value it passed to retproc / return) and stores it in $result. Wait for the coroutine first with cowait if it may still be running.

Examples

    corunproc compute 42
    cowait $coid
    coresult $coid
    echo $result

Exit status

0       Result retrieved.
>0      Unknown coroutine id, or it has not completed.

See also

corunproc, cowait, colist

coresume back to top ↑

resume a suspended coroutine

Synopsis

    coresume <coid>

Description

Resumes a coroutine previously paused with cosuspend, letting it continue from where it yielded.

Examples

    cosuspend $coid
    coresume $coid

Exit status

0       Resume requested.
>0      Unknown coroutine id, or it was not suspended.

See also

cosuspend, cocancel, corunproc, colist

corunproc back to top ↑

start a procedure as a concurrent coroutine

Synopsis

    corunproc <procedure> [arg ...]

Description

Starts a named proc running as a coroutine on its own cooperative task, returning immediately. The new coroutine's id is published in $coid; use it with cowait, coresult, cosuspend, coresume, and cocancel. Each coroutine gets its own variable scope; use coget / coset / coincr / codecr / cocas for thread-safe shared state, and the mutex / semaphore / event / barrier / channel primitives to coordinate.

Examples

    corunproc worker 1 2 3
    set id = $coid
    cowait $id
    coresult $id

Exit status

0       Coroutine started.
>0      No such procedure, or bad arguments.

See also

cowait, coresult, cocancel, cosuspend, coresume, colist, wait

coset back to top ↑

set a thread-safe atomic variable

Synopsis

    coset <name> <value>

Description

Stores value under name in cshw's atomic-variable table -- a thread-safe key/value store shared across coroutines and worker threads, SEPARATE from ordinary shell variables set with `set`. Read it back with coget, or use coincr / codecr / cocas for atomic numeric updates.

Examples

    coset counter 0
    coset owner ""

Exit status

0       Stored.
>0      Bad usage.

See also

coget, coincr, codecr, cocas, corunproc

cosuspend back to top ↑

suspend a running coroutine

Synopsis

    cosuspend <coid>

Description

Pauses a running coroutine at its next cooperative checkpoint. Resume it later with coresume. Suspending does not lose the coroutine's state or result.

Examples

    cosuspend $coid
    coresume $coid

Exit status

0       Suspend requested.
>0      Unknown coroutine id.

See also

coresume, cocancel, corunproc, colist

cowait back to top ↑

wait for coroutine(s) to complete

Synopsis

    cowait /all
    cowait /any [/timeout:ms]
    cowait [/timeout:ms] <coid> [coid ...]
    wait

Description

Blocks until coroutines finish. You must say which: /all waits for every running coroutine, /any returns as soon as one finishes (and sets $coid to it), or list explicit coroutine ids. With none of these, cowait is a usage error. /timeout:ms bounds the wait and reports a timeout if it elapses first. `wait` is a convenience alias equivalent to `cowait /all`.

Options

    /all          Wait for all running coroutines.
    /any          Return when any one finishes; sets $coid to it.
    /timeout:ms   Give up after ms milliseconds (sets a timeout status).

Examples

    corunproc a ; corunproc b
    wait                          # == cowait /all
    cowait /any /timeout:5000
    cowait $id1 $id2

Exit status

0       The awaited coroutine(s) completed.
>0      Timed out, bad coroutine id, or no /all|/any|ids given.

See also

corunproc, coresult, cocancel, colist

cp back to top ↑

copy files (alias for copy)

Synopsis

    cp [-r | -R | --recursive] <source> <dest>

Description

`cp` is identical to `copy`. See `man copy` for full documentation, options, and examples.

See also

copy, mv, rm

createwindow back to top ↑

create a script-owned window on the UI thread

Synopsis

    createwindow [<class>] [<title>] [/style:a,b,...] [/exstyle:a,b,...]
                 [/pos:x,y] [/size:w,h] [/parent:<hwnd>] [/id:<n>]

Description

Creates a Win32 window on the CSHW UI thread and returns its HWND in $result (hex), plus a monotonic per-window cookie in $result_cookie that scripts can use to guard against the HWND-reuse window.

The window's whitelisted messages (WM_COMMAND, WM_NOTIFY, WM_TIMER, WM_LBUTTONDOWN/UP, WM_KEYDOWN, WM_SIZE, WM_CLOSE, WM_DESTROY) are routed back to bound script procs via `bindevent`.

Options

    <class>     Window class. Default: CSHWScriptWindowClass (the built-in
                generic script window). Plugin-registered classes are
                also accepted by name.
    <title>     Window text. Default: empty.
    /style:..   Comma-separated WS_* flags. Accepts symbolic names
                (overlapped, visible, sysmenu, thickframe, tabstop,
                child, popup, ...) and hex/decimal literals.
                Default: WS_OVERLAPPEDWINDOW|WS_VISIBLE for top-levels,
                WS_CHILD|WS_VISIBLE when /parent is given.
    /exstyle:.. WS_EX_* flags (topmost, toolwindow, clientedge, ...).
                Same comma-list syntax.
    /pos:x,y    Top-left position. Default: CW_USEDEFAULT.
    /size:w,h   Window size. Default: CW_USEDEFAULT.
    /parent:<hwnd>
                Parent HWND for child windows.
    /id:<n>     HMENU / child-id slot.

Examples

    createwindow "" "My window" /size:400,300
    set w = $result
    # Add a child button:
    addcontrol button $w "&OK" /pos:10,10 /size:80,25 /id:100
    # React to its click:
    proc on_ok
        echo "ok clicked, ctlId=$1 code=$2"
    endproc
    bindevent $w command 100 on_ok

Exit status

0       Success; $result is the HWND in hex, $result_cookie the cookie.
1       UI thread unavailable, unknown class, or bad style/pos/size.

Notes

The built-in CSHWScriptWindowClass has its dispatcher wired directly into its WndProc. For any OTHER class (plugin class, system control, foreign HWND), CSHW installs a SetWindowSubclass shim on top so the window is bindable-by-default.

See also

addcontrol, bindevent, unbindevent, sendmessage, postmessage

crond back to top ↑

cron daemon control

Synopsis

    crond start
    crond stop
    crond status
    crond restart

Description

Controls the cron daemon that executes scheduled jobs defined in crontab. The daemon runs in the background, checking every minute for jobs to run.

Options

    start           Start the cron daemon.
    stop            Stop the cron daemon.
    status          Show daemon status.
    restart         Stop then start the daemon.

Examples

    crond start
        Start the cron daemon.

    crond status
        Check if daemon is running.

    crond stop
        Stop the daemon.

    crond restart
        Restart after crontab changes.

Exit status

0       Success
1       Daemon already running/stopped
2       Error starting/stopping

Notes

Background Process: crond runs as a background thread within CSHW. It continues running as long as the shell is open.

Auto-Start: To have crond start automatically, add 'crond start' to your shell startup script.

Job Execution: Jobs run in separate processes. Their output goes to a log file or is discarded depending on configuration.

Missed Jobs: If crond is not running when a job is scheduled, that execution is missed. crond does not run missed jobs.

Windows Task Scheduler: For persistent scheduled tasks that survive logoff/reboot, consider using Windows Task Scheduler instead: schtasks /create ...

See also

crontab, jobs, service

crontab back to top ↑

manage scheduled cron jobs

Synopsis

    crontab -l
    crontab -e
    crontab -r
    crontab FILE

Description

Manages the cron job schedule for the current user. Cron jobs are commands that run automatically at specified times. CSHW provides a UNIX-compatible cron implementation on Windows.

Options

    -l, --list      List current cron jobs.
    -e, --edit      Edit crontab (opens in editor).
    -r, --remove    Remove all cron jobs.
    FILE            Install cron jobs from FILE.

Examples

    crontab -l
        List all scheduled jobs.

    crontab -e
        Edit cron schedule in text editor.

    crontab jobs.txt
        Install jobs from file.

    crontab -r
        Remove all scheduled jobs.

Crontab file format (5 time fields + command):
    # minute hour day month weekday command
    0 * * * * echo "Runs every hour"
    30 9 * * 1-5 backup.bat
    0 0 1 * * monthly_report.exe
    */15 * * * * check_status.bat

Exit status

0       Success
1       Error reading/writing crontab
2       Syntax error in crontab

Notes

Time Field Format: Field Values Special ───── ────── ─────── Minute 0-59 * (any), */n (every n) Hour 0-23 , (list), - (range) Day 1-31 Month 1-12 Weekday 0-6 (0=Sun)

Special Characters: * Any value */n Every n units (*/15 = every 15) , List (1,3,5) - Range (1-5)

Examples: 0 * * * * Every hour at :00 */15 * * * * Every 15 minutes 0 9 * * 1-5 9 AM on weekdays 0 0 1 * * Midnight on 1st of month 30 4 * * 0 4:30 AM on Sundays

Cron Daemon: Jobs only run if crond is running. Start with 'crond start'.

Storage: Crontab is stored in %APPDATA%\cshw\crontab.

See also

crond, time, sleep

cut back to top ↑

remove sections from each line

Synopsis

    cut -d DELIM -f FIELDS [FILE]
    cut -c CHARS [FILE]
    command | cut [options]

Description

Extracts selected portions of each line from files or standard input. Useful for processing delimited data like CSV files or extracting specific columns from command output.

Options

    FILE            File to process (default: stdin).

    -d DELIM        Use DELIM as field delimiter (default: tab).
    -f FIELDS       Select fields (columns). Examples:
                    -f 1        First field
                    -f 1,3      Fields 1 and 3
                    -f 1-3      Fields 1 through 3
                    -f 2-       Field 2 to end

    -c CHARS        Select characters by position.
                    -c 1-10     Characters 1-10
                    -c 5        Character 5 only

    -s              Suppress lines without delimiters.

Examples

    cut -d, -f1 data.csv
        Extract first column from CSV file.

    cut -d, -f1,3,5 data.csv
        Extract columns 1, 3, and 5.

    cut -d: -f1 /etc/passwd
        Extract usernames (UNIX password file format).

    echo "hello world" | cut -c1-5
        Extract "hello".

    processlist | cut -c1-40
        Truncate process list output.

    dir /b | cut -d. -f1
        Extract filenames without extensions.

Exit status

0       Success
1       Error

Notes

Delimiters: Common delimiters: - Comma: -d, - Tab: -d$'\t' (or default) - Colon: -d: - Space: -d' '

Field vs Character: - Use -f for delimited data (CSV, TSV) - Use -c for fixed-width data

One Delimiter Only: cut uses a single character as delimiter. For multi-character delimiters or complex parsing, consider using grep or scripting.

See also

grep, sort, wc, tr

date back to top ↑

display or format the current date and time

Synopsis

    date [options]
    date +FORMAT

Description

Displays the current date and time. By default, shows the local date and time in a readable format. Various options control the output format.

Options

    -u, --utc       Display time in UTC (Coordinated Universal Time)
    -I, --iso       Display in ISO 8601 format (YYYY-MM-DDTHH:MM:SS)
    -R, --rfc       Display in RFC 2822 format (for email headers)
    +FORMAT         Custom format string (see FORMAT SPECIFIERS)

Format Specifiers

    %Y    Four-digit year (e.g., 2024)
    %m    Month as two digits (01-12)
    %d    Day of month as two digits (01-31)
    %H    Hour in 24-hour format (00-23)
    %M    Minute (00-59)
    %S    Second (00-59)
    %j    Day of year (001-366)
    %w    Day of week (0-6, Sunday=0)
    %W    Week number of year (00-53)
    %a    Abbreviated weekday name (Sun, Mon, ...)
    %A    Full weekday name (Sunday, Monday, ...)
    %b    Abbreviated month name (Jan, Feb, ...)
    %B    Full month name (January, February, ...)
    %p    AM or PM
    %Z    Timezone name
    %%    Literal percent sign

Examples

    date
        Wed Jan 08 14:30:45 2025

    date -u
        Wed Jan 08 19:30:45 2025 UTC

    date -I
        2025-01-08T14:30:45

    date -R
        Wed, 08 Jan 2025 14:30:45 -0500

    date +%Y-%m-%d
        2025-01-08

    date "+%H:%M:%S"
        14:30:45

    date "+Today is %A, %B %d"
        Today is Wednesday, January 08

Notes

Unlike Unix date, this command cannot set the system date/time. Use Windows 'control timedate.cpl' to change the system time.

See also

time, uptime

dc back to top ↑

reverse-Polish arbitrary-precision calculator

Synopsis

    dc                              interactive REPL
    dc "COMMANDS"                   run commands from argv
    dc -e "CMDS" [-e "CMDS"...]     inline (repeatable)
    dc -f FILE [-f FILE...]         script from file (repeatable)
    dc -i                           force REPL even with redirected stdin

Description

dc is bc's reverse-Polish sibling. Numbers push to a value stack; single-character commands operate on the top. Same arbitrary-precision math backend as bc (Gavin Howard's BCL); completely different surface.

dc came first historically (1970, PDP-7); bc was originally a preprocessor that translated infix syntax into dc commands. Today they're separate languages.

Arithmetic

    + - * / %       pop two; push result
    ^               power
    v               sqrt (pops one)
    _N              negative literal prefix (e.g. _5 pushes -5)

Stack

    c               clear stack
    d               duplicate top
    r               swap top two
    z               push current stack depth
    p               print top with newline (does NOT pop)
    n               print top with no newline (POPS)
    f               print whole stack top-down

Registers

Single-character register names. Numeric and macro values stored
separately.

    sR              pop top and store into register R
    lR              push register R's value (default 0 if unset);
                    if R holds a macro, push it onto the macro stash
    [BODY]          push macro string
    x               pop a macro and execute it
    <R >R =R        pop two values; execute R as a macro if first<second
                    (i.e. earlier-pushed < later-pushed) / first>second
                    / first==second. Comparison semantics follow POSIX
                    and Gavin Howard.
    !<R !>R !=R     same with the condition negated

.SCALE / BASE
    k               pop value N, set scale to N
    K               push current scale
    i               pop value N, set ibase to N
    I               push current ibase
    o               pop value N, set obase to N
    O               push current obase

Quit

    q               end the script
    Q               pop a count, end script

Examples

    dc "1 2 +p"                                 -> 3
    dc "20k 1 3/p"                              -> .33333333333333333333
    dc "20k 2vp"                                -> 1.41421356237309504880  (sqrt 2)
    dc "_5 3+p"                                 -> -2
    dc "2o 10p"                                 -> 1010   (binary output)
    dc "16o 255p"                               -> FF     (hex output)
    dc "5sn lnln*p"                             -> 25     (square via register)
    dc "[1+]sa 5 lax p"                         -> 6      (macro: add one)
    dc "[d 1- d 1>f *]sf 5 lfx p"               -> 120    (factorial via recursion)

Repl

With no inline source and a TTY stdin, dc enters an interactive REPL
showing `dc> ` between lines. Each typed line is executed atomically.
Type `q` to return to cshw.

.SEE ALSO
    bc(1)               the infix sibling

Notes

Implementation: BCL arithmetic + a cshw-written stack VM. Many extended dc commands from GNU / OpenBSD dc are not implemented in this release (~ R Z X ; : S L P |); they may land in a future cshw version if demand arises.

declare back to top ↑

declare a variable with optional type / scope flags

Synopsis

    declare [-r] [-l] [-a] [-A] <name> [= <value>]

Description

Declares one variable, optionally marking it read-only (-r), local to the current proc (-l), an indexed array (-a), or an associative array (-A). Without flags, behaves like `set`.

The flags can be combined (e.g., `declare -lr CONST = 42` declares a local read-only constant inside a proc).

Options

    -r          Mark the variable read-only (same as `readonly`).
    -l          Declare in the local proc scope (same as `local`).
    -a          Declare as an indexed array.
    -A          Declare as an associative array (hash).
    <name>      Variable name.
    <value>     Optional initial value.

Examples

    declare -r MAX = 100
        # Read-only global.

    declare -lr loop_count = 0
        # Read-only local (only meaningful inside a proc).

    declare -a colors = (red green blue)
        # Declare and fill in one line. Subscripts are 1-BASED:
        # $colors[1] is "red".

    declare -a more
    set more[1] = "red"
    set more[2] = "green"
        # An empty array, then elements by index. `set more[0]` is a
        # syntax error, not element 1 -- counting starts at 1.

    declare -A users
    hash set users alice admin
    hash set users bob   user
    echo $users[alice]
        # Hash entries are written with `hash set` and read with
        # $name[key]. There is no `set users{alice}` form: it parses,
        # does nothing, and returns 0.

Exit status

0       Declaration succeeded.
1       Bad flag combination, syntax error, or read-only violation.

-a and -A differ only in case and ask for different containers, so giving both is refused rather than one of them quietly winning.

Notes

`declare` is the unified form for the related single-purpose commands: declare -r ... <=> readonly ... declare -l ... <=> local ... declare -a ... <=> array <name> declare -A ... <=> hash <name>

The single-purpose commands remain available; pick whichever reads more naturally in your script.

The flags used to do nothing. They are leading options, so the switch extractor consumed them before the command ran: `declare -a colors = (red green blue)` was byte-identical to the same line without the -a, a plain string with $#colors == 1. It hid well, because `foreach c ($colors)` still iterated three times -- foreach splits the string itself -- and `declare -A cfg` looked right whenever a `hash set` followed, since that creates the hash on its own.

See also

set, local, readonly, array, hash, share

del back to top ↑

delete files

Synopsis

    del <file> [<file> ...]
    del /secure  <file> [<file> ...]
    del /recycle <file> [<file> ...]

Description

Deletes one or more files. 'del' and 'rm' are aliases for the same handler; see rm(1) for the full description.

By default del permanently deletes the named files. Use /recycle to send them to the Recycle Bin (recoverable), or /secure to overwrite the file contents with zeros before deletion.

cshw accepts both Windows-style and Unix-style switch spellings. See rm(1) and rmdir(1) for the full set.

Options

    <file>          File(s) to delete.

    /secure, --secure
                    Overwrite the file contents with zeros before
                    deletion. Mutually exclusive with /recycle.

    /recycle, --recycle
                    Send to the Recycle Bin. Fails (rather than silently
                    permanent-deleting) when the bin is unavailable; see
                    NOTES on rmdir(1).

Examples

    del temp.txt
        Permanently delete temp.txt.

    del /recycle scratch.bin
        Send scratch.bin to the Recycle Bin.

    del /secure passwords.txt
        Zero out and then delete.

See also

rm, rmdir

df back to top ↑

display disk free space

Synopsis

    df
    df [DRIVE]
    df [options]

Description

Reports file system disk space usage. Shows total, used, and available space on mounted drives.

Options

    DRIVE           Show info for specific drive (e.g., C:).

    -h, --human-readable
                    Print sizes in human readable format (KB, MB, GB).
    -a, --all       Accepted for compatibility. Network and removable
                    drives are listed either way; only drives with no
                    media, such as an empty optical drive, are omitted.

Examples

    df
        Show disk usage for all local drives.

    df C:
        Show disk usage for C: drive only.

    df -h
        Human-readable format (1K, 234M, 2G).

    df .
        Show the filesystem holding the current directory.

    df C:\Users
        Show the filesystem holding a path, which may be a mount point
        rather than the drive letter it starts with.

Exit status

0       Success
1       Error (invalid drive)

Notes

Output Columns: - Filesystem: Drive letter or mount point - Size: Total capacity - Used: Space in use - Avail: Space available - Use%: Percentage used - Mounted on: Drive description

Windows Drives: Shows fixed, removable and network drive letters. A drive with no media in it is skipped.

Operands are resolved, not sliced: `df C:` and `df C:\Users\you\project` both report the volume that actually holds the path, so a mounted folder reports its own volume rather than the letter its path happens to start with. The operand was ignored entirely before -- every form of df printed every drive.

See also

du, dir, stat

diff back to top ↑

compare files line by line

Synopsis

    diff FILE1 FILE2
    diff [options] FILE1 FILE2

Description

Compares two files line by line and displays the differences. Output shows which lines need to be added, removed, or changed to transform FILE1 into FILE2.

Options

    FILE1           First file to compare.
    FILE2           Second file to compare.

    -u, --unified   Output in unified diff format (shows context).
    -c, --context   Output in context diff format.
    -i, --ignore-case
                    Ignore case differences.
    -w, --ignore-whitespace
                    Ignore all whitespace.
    -b              Ignore changes in amount of whitespace.
    -B              Ignore blank lines.
    -q, --brief     Report only whether files differ.

Examples

    diff old.txt new.txt
        Compare two files and show differences.

    diff -u original.cpp modified.cpp
        Unified diff format (commonly used for patches).

    diff -i file1.txt file2.txt
        Case-insensitive comparison.

    diff -q dir1/file dir2/file
        Quick check if files differ.

    diff -w config.old config.new
        Ignore whitespace differences.

Exit status

0       Files are identical
1       Files differ
2       Error (file not found, etc.)

Notes

Output Format: Default output uses traditional diff format: - Lines with < are from FILE1 - Lines with > are from FILE2 - Numbers indicate line positions

Unified Format (-u): - Lines with - are removed - Lines with + are added - Context lines are shown with space prefix

Use Cases: - Comparing code versions - Checking configuration changes - Creating patches

Binary Files: diff is designed for text files. Binary files will be reported as different but content won't be meaningfully shown.

See also

type, wc, grep

dir back to top ↑

display directory contents

Synopsis

    dir [path] [options]
    dir [path] [/switches]

Description

Displays a list of files and subdirectories in a directory. Similar to the Windows DIR command but with additional formatting options and UNIX-style switch support.

By default, dir displays filenames, sizes, dates, and attributes. The output can be customized using various switches to show different information, sort results, filter by attributes, and control formatting.

Options

    path            Directory or file pattern to list (default: current directory)
                    Supports wildcards: * (any characters) and ? (single character)

    Attribute filters:

    Hidden and system files are OMITTED unless asked for, as in cmd.exe.
    Without that, `dir` in a home directory buries the answer under
    NTUSER.DAT, ntuser.dat.LOG1, Cookies, NetHood and a dozen more.

    /a              Show all files including hidden and system
    /ah             Show only hidden files
    /as             Show only system files
    /ar             Show only read-only files
    /aa             Show only files with archive attribute
    /ad             Show only directories
    /a-h            Exclude hidden files
    /a-s            Exclude system files
    /a-d            Exclude directories (files only)

    Sorting options:
    /o              Sort by name (ascending)
    /o-             Sort by name (descending)
    /on             Sort by name
    /os             Sort by size (smallest first)
    /o-s            Sort by size (largest first)
    /oe             Sort by extension
    /od             Sort by date/time (oldest first)
    /o-d            Sort by date/time (newest first)
    /og             Group directories first

    Display options:
    /b              Bare format (names only, no header/footer)
    /w              Wide format (multiple columns)
    /p              Pause after each screenful
    /l              Use lowercase for filenames
    /n              Use long list format with new format
    /q              Show file owner
    /r              Include alternate data streams
    /s              Recurse into subdirectories
    /x              Show short (8.3) filenames

    Time display:
    /tc             Show creation time
    /ta             Show last access time
    /tw             Show last write time (default)

    Format options:
    /4              Use 4-digit years in dates
    /24             Use 24-hour time format
    /-c             Disable thousand separators in sizes
    /attr           Show file attributes column

    Banner and summary:

    Both are ON by default, matching cmd.exe. Turn them off for the
    session with a setting, or for one listing with a switch:

        set nodirbanner     drop the " Directory of C:\path" line
        set nodirsummary    drop the "N File(s) ... bytes free" block
        unset nodirbanner   put it back

        /banner  /summary   on, for this invocation
        /-banner /-summary  off, for this invocation

    /header and /footer are accepted as aliases, because that is what a
    cmd user will reach for first. The names above are the documented
    ones: "header" is ambiguous in a listing -- a table can have column
    headers -- while a banner cannot be misread, and "summary" is
    Microsoft's own word for the bottom block. cmd's own /B help reads
    "no heading information or summary".

    The settings are spelled negatively because ON is the default, and
    csh already names a switch you disable that way -- noclobber,
    noglob, nonomatch.

    A switch beats the setting in both directions, so a session with
    `set nodirbanner` can still ask for the banner once with /banner.

    /b (bare) suppresses both regardless, as it always has.

    Nothing matched:

    When no entry survives the pattern and the attribute filter, dir
    prints "File Not Found" and returns 1 -- cmd's wording and cmd's
    behaviour. An empty listing at status 0 is indistinguishable from an
    empty directory, so `dir /a:h` with no hidden files, `dir *.zzz` and
    `dir` in an empty folder used to be the same silent answer.

    /b stays silent as it always has, but still returns 1.

Examples

    dir
        List contents of current directory.

    dir C:\Users
        List contents of C:\Users directory.

    dir *.txt
        List all text files in current directory.

    dir /s *.exe
        Recursively find all .exe files.

    dir /ah
        Show only hidden files.

    dir /ad
        Show only directories.

    dir /o-s
        Sort by size, largest first.

    dir /o-d /s
        Recursively list, newest files first.

    dir /b > filelist.txt
        Export bare file listing to a file.

    dir /b /s *.cpp
        Recursively list all .cpp files (paths only).

    dir /q
        Show file owners.

    dir /attr
        Show detailed file attributes.

    dir /w
        Wide format listing (multiple columns).

Exit status

0       Success
1       Directory not found or access denied
2       Invalid argument

Notes

The dir command automatically formats file sizes with thousand separators for readability (e.g., 1,234,567 bytes). Use /-c to disable this.

For very large directories, consider using /p to pause between screens, or redirect output to a file or grep command.

File sizes are shown in bytes by default. Very large files (>1TB) may show approximate sizes.

See also

cd, find, grep, ls, stat

dirname back to top ↑

strip the last component from a path

Synopsis

    dirname <path>

Description

Print <path> with its last component removed, leaving the directory portion. Both forward slashes and backslashes are recognized as path separators, and trailing separators are ignored.

When <path> contains no directory component, dirname prints "." -- the current directory.

dirname does not touch the filesystem; it is a pure text operation on the path you give it.

Examples

    dirname /usr/lib/file.txt
        Prints: /usr/lib

    dirname file.txt
        Prints: .

    dirname /usr/lib/
        Prints: /usr  (the trailing slash is ignored)

Exit status

Zero on success. dirname with no path argument is a usage error.

See also

basename, realpath

dirs back to top ↑

display directory stack

Synopsis

    dirs
    dirs [options]

Description

Displays the directory stack maintained by pushd and popd commands. The stack shows directories in order from most recent (top) to oldest.

Options

    -c, --clear     Clear the directory stack.
    -l, --long      Show full paths (don't abbreviate home directory).
    -p              Print one directory per line.
    -v              Print with index numbers.

Examples

    dirs
        Show directory stack.

    pushd C:\Projects
    pushd C:\Temp
    pushd C:\Users
    dirs
        # C:\Users C:\Temp C:\Projects C:\OriginalDir

    dirs -v
        # 0  C:\Users
        # 1  C:\Temp
        # 2  C:\Projects
        # 3  C:\OriginalDir

    dirs -c
        Clear the stack.

Exit status

0       Success

Notes

$dirstack: The stack is also a variable. $dirstack[1] is the CURRENT directory and deeper indices are the pushd stack with the most recently pushed first, which is both the order `dirs` prints and the order tcsh uses. It moves with `cd` as well as with pushd and popd, and `dirs -c` leaves it holding just the current directory.

pushd libs
echo "came from $dirstack[2]"

$dirstack was always empty before, so a script could read the text `dirs` prints but had no way to get at an entry.

Stack Order: - Index 0 is the current directory - Higher indexes are older entries - pushd adds to stack, popd removes

Empty Stack: If no directories have been pushed, dirs shows only the current directory.

Navigation: Use pushd/popd for efficient navigation between multiple working directories.

See also

pushd, popd, cd

disown back to top ↑

release a job without stopping the process

Synopsis

    disown [%JOBID]
    disown

Description

Removes a job from this shell's job table without touching the process. The process keeps running; cshw simply stops tracking it.

After disowning, the job no longer appears in 'jobs', is not waited for by 'wait', and does not trigger the unfinished-jobs warning when the shell exits.

With no argument, releases the current job (%+).

Options

    %JOBID          Job to release. Accepts %1, %%, %+, %-, %name, or a
                    bare job number.

Examples

    longbuild.exe &
        # [1] 24680
    disown %1
        # [1] 24680 released (still running)
    jobs
        # No jobs.

    adopt 41288
    disown %1
        Adopted the wrong process; put it back the way it was.

Exit status

0       Released
1       No such job, or the job is a coroutine

Notes

Coroutine jobs cannot be disowned. A coroutine is a thread inside cshw and cannot outlive the shell -- shutdown cancels it regardless -- so "forget about it but leave it running" is not something that can be honoured. Use 'cocancel' to stop one.

Disowning does not detach the process from the console it shares with cshw. A console program that is still writing will keep writing to your terminal.

See also

adopt, jobs, bg, fg, kill, cocancel

dllimport back to top ↑

load DLL for function calls

Synopsis

    dllimport PATH
    dllimport PATH ALIAS

Description

Loads a Dynamic Link Library (DLL) into the shell process for later use with rundllproc. The DLL remains loaded until explicitly unloaded or the shell exits.

Options

    PATH            Path to the DLL file.
    ALIAS           Optional short name to reference the DLL.

Examples

    dllimport C:\MyApp\helper.dll
        Load DLL by path.

    dllimport C:\MyApp\helper.dll myhelper
        Load DLL with alias "myhelper".

    dllimport kernel32.dll
        Load system DLL.

    dllimport "C:\Program Files\App\plugin.dll" plugin
        Load DLL with spaces in path.

    # Then use with rundllproc:
    rundllproc myhelper DoSomething

Exit status

0       Success
1       DLL not found
2       Load failed (dependencies missing, wrong architecture)
3       Alias already in use

Notes

Dependencies: The DLL and all its dependencies must be available. Check with peinfo or Dependency Walker if loading fails.

Architecture: 32-bit DLLs can only be loaded by 32-bit CSHW. 64-bit DLLs can only be loaded by 64-bit CSHW.

Persistence: Loaded DLLs remain in memory until: - Explicitly unloaded with dllunload - Shell exits

Use Cases: - Calling custom DLL functions - Automation with COM objects - Extending shell functionality - Testing DLL code

Security: Only load DLLs you trust. Malicious DLLs can execute arbitrary code in the shell process.

See also

dllunload, dlllist, rundllproc

dlllist back to top ↑

list imported DLLs

Synopsis

    dlllist

Description

Lists all DLLs currently loaded via dllimport. Shows the alias (if any) and full path for each loaded DLL.

Examples

    dlllist
        # myhelper    C:\MyApp\helper.dll
        # plugin      C:\Program Files\App\plugin.dll
        # kernel32    C:\Windows\System32\kernel32.dll

    dllimport C:\test.dll test
    dlllist
        # test        C:\test.dll

Exit status

0       Success (always)

Notes

Empty List: If no DLLs have been imported, dlllist shows nothing.

System DLLs: Only DLLs explicitly loaded with dllimport are shown, not DLLs loaded automatically by the shell or Windows.

Management: Use dlllist to see what's loaded before: - Calling rundllproc - Unloading with dllunload - Debugging DLL issues

See also

dllimport, dllunload, rundllproc

dllunload back to top ↑

unload a previously imported DLL

Synopsis

    dllunload ALIAS
    dllunload PATH

Description

Unloads a DLL that was previously loaded with dllimport. Frees the DLL from memory and removes it from the import cache.

Options

    ALIAS           Alias assigned during dllimport.
    PATH            Original path used in dllimport.

Examples

    dllunload myhelper
        Unload DLL by alias.

    dllunload C:\MyApp\helper.dll
        Unload DLL by path.

    dlllist
    # helper (C:\MyApp\helper.dll)
    dllunload helper
    dlllist
    # (empty)

Exit status

0       Success
1       DLL not found in cache

Notes

Reference Counting: If other code still holds references to the DLL, it may not be fully unloaded from memory until all references are released.

Cleanup: It's good practice to unload DLLs when done, but they're automatically cleaned up when the shell exits.

Error Handling: Unloading a DLL while code is executing from it can cause crashes. Ensure no operations are in progress.

See also

dllimport, dlllist, rundllproc

du back to top ↑

estimate file space usage

Synopsis

    du [path]
    du [options] [path]

Description

Estimates and displays the disk space used by files and directories. Useful for finding large files or directories consuming disk space.

Options

    path            Directory to analyze (default: current directory).

    -h, --human-readable
                    Print sizes in human readable format (KB, MB, GB).
    -s, --summarize Show only total for each argument.
    -a, --all       Show sizes for all files, not just directories.
    -d N, --max-depth=N
                    Show totals for directories N levels deep.

Examples

    du
        Show disk usage for current directory tree.

    du -h
        Human-readable output.

    du -s *
        Summary of each item in current directory.

    du -h -s C:\Users
        Total size of Users directory.

    du -d 1
        Show only immediate subdirectories.

    du -h -d 2 C:\Projects
        Show projects with 2 levels of detail.

    du -a | sort -n | tail -20
        Find 20 largest items.

Exit status

0       Success
1       Path not found
2       Access denied to some directories

Notes

Performance: du must traverse the entire directory tree, which can be slow for large directories or network drives.

Access Denied: Some directories may be inaccessible. du continues with accessible directories and reports errors for inaccessible ones.

Symbolic Links: Symbolic links are not followed by default to prevent counting the same files multiple times.

Finding Large Directories: du -h -d 1 | sort -h | tail -10

See also

df, dir, stat

echo back to top ↑

display text or variable values

Synopsis

    echo [text...]
    echo $variable
    echo "text with $variable expansion"

Description

Displays a line of text or the value of variables to standard output. The echo command performs variable expansion, substituting $variable references with their actual values.

echo is fundamental for shell scripts, debugging, and creating output. It supports both simple text display and complex variable interpolation.

Options

    text            The text to display. Multiple arguments are separated
                    by spaces in the output.

    Variables are expanded:
    $name           Expands to the value of shell variable 'name'
    $?              Expands to the last command's exit code
    $:              Expands to the current working directory
    $$              Expands to the shell's process ID

Examples

    echo Hello World
        Displays: Hello World

    echo $PATH
        Displays the value of the PATH environment variable.

    echo "Current directory: $:"
        Shows current directory with label.

    echo "Last exit code was $?"
        Shows the previous command's exit code.

    echo The answer is $answer
        Variable expansion in unquoted text.

    echo "Hello, $name! Welcome to $:"
        Multiple variable expansions in one string.

    echo
        Outputs an empty line.

    echo "Line 1" > file.txt
        Redirect echo output to a file.

    echo "Another line" >> file.txt
        Append echo output to a file.

Exit status

0       Success (always, unless I/O error)

Notes

$echo_style: Which of the two incompatible echoes this is, as in tcsh:

bsd     -n suppresses the trailing newline; backslash escapes are
        literal. This is the default and what cshw has always done.
sysv    Backslash escapes are interpreted; -n is an ordinary word
        and gets printed.
both    Both.
none    Neither.

Under sysv and both, these escapes are expanded: \a \b \e \f \n \r \t \v \ and \0nnn (up to three octal digits). \c stops output there and suppresses the newline. A backslash sequence echo does not recognize is left as written rather than having its backslash swallowed.

All four values used to behave as bsd, so a ported script that set sysv to get \t and \n interpreted printed the backslashes instead, at status 0.

Variable Expansion: Variables prefixed with $ are automatically expanded. To display a literal dollar sign, you can escape it or use single quotes in scripts.

Unlike UNIX echo, CSHW's echo does not support -n (no newline) or -e (escape sequences) flags. Each echo command outputs a newline.

Empty Variables: If a variable is not defined, $variable expands to an empty string without generating an error.

Quoting: Use double quotes to preserve spaces and ensure proper variable expansion. Without quotes, multiple spaces between words may collapse to single spaces.

See also

set, type, printf

enable back to top ↑

Enable or disable a built-in (bash's spelling of shadow).

endsplash back to top ↑

dismiss the modeless splash dialog

Synopsis

    endsplash

Description

Dismisses the modeless splash dialog put up by `splash`. Safe to call when no splash is showing -- it's a clean no-op.

Examples

    splash
    # ... long-running work ...
    endsplash

Exit status

0       Always (success even when no splash is showing).

See also

splash, progressdlg

env back to top ↑

display or modify environment

Synopsis

    env
    env NAME=VALUE... COMMAND
    env -u NAME COMMAND

Description

Displays all environment variables or runs a command with a modified environment. Useful for temporarily changing environment variables for a single command without affecting the shell's environment.

Options

    Without arguments, displays all environment variables.

    NAME=VALUE      Set variable for the command.
    -u NAME         Unset variable for the command.
    -i              Start with empty environment.
    COMMAND         Command to run with modified environment.

Examples

    env
        Display all environment variables.

    env | grep PATH
        Show PATH-related variables.

    env DEBUG=1 myprogram.exe
        Run program with DEBUG=1 set.

    env -u PROXY myprogram.exe
        Run program with PROXY unset.

    env PATH="C:\Tools;%PATH%" tool.exe
        Run with modified PATH.

    env -i TERM=xterm program.exe
        Run with minimal environment.

Exit status

0       Success (or command's exit code)
1       Error

Notes

Temporary Changes: env changes don't affect the shell. After the command completes, the environment is unchanged: env DEBUG=1 program.exe # DEBUG is NOT set here

Display Format: Variables are shown as NAME=VALUE, one per line.

Sorting: Output is typically sorted alphabetically by name.

Comparison: - env: Display or temporarily modify environment - setenv: Permanently set in current shell - printenv: Display only (no modification)

See also

setenv, unsetenv, printenv, set

eval back to top ↑

concatenate arguments and run the result as a command

Synopsis

    eval [argument ...]

Description

Join the arguments together with single spaces and run the resulting string as a command in the current shell. The arguments have already been through one round of the shell's tokenizing and expansion; running the joined string back through the shell triggers a second round.

That second round is the whole point of eval. Use it when: - a command line has been built up inside a variable - variable or command-substitution expansion must be deferred until the moment eval runs, rather than when the line was first parsed

eval runs in the current shell, so any variable assignments, cd, or other state changes made by the evaluated command persist.

Examples

    set cmd = "echo hello"
    eval $cmd
        Runs: echo hello

    eval 'echo $HOME'
        The single quotes stop $HOME from expanding when the line is
        first read; eval expands it on the second pass.

    set assign = "set count = 5"
    eval $assign
        $count is now 5 in the current shell.

Exit status

The exit status is that of the evaluated command. eval with no arguments is a successful no-op.

Notes

Quoting from the first parse is intentionally not preserved -- eval's contract is to re-parse. `eval echo "a b"` runs `echo a b`, passing two arguments.

See also

source, exec, set

event back to top ↑

manual/auto-reset event signal

Synopsis

    event <name> create [/manual]
    event <name> signal
    event <name> reset
    event <name> wait
    event <name> trywait [/timeout:ms]
    event <name> pulse
    event <name> destroy

Description

A named Win32-style event for signaling between coroutines and threads. Auto-reset by default (one waiter is released per signal, then the event resets); with /manual it stays signaled until reset, releasing all waiters. Create it before signal/reset/wait/pulse -- operating on an unknown name is an error.

Options

    create [/manual]    Create the event (auto-reset unless /manual).
    wait                Block until signaled. FATAL on timeout -- see below.
    trywait [/timeout:ms]
                        Poll (or wait up to ms); $? = 0 signaled, 1 not.
                        Never fatal.
    signal              Set to the signaled state.
    reset               Return to the non-signaled state.
    wait [/timeout:ms]  Block until signaled; $? = 0 signaled, 1 timeout.
    pulse               Signal, releasing current waiters, then reset.
    destroy             Remove the event.

ON FAILURE
`wait` is FATAL: "wait" means do not continue until this has happened, so a
timeout -- meaning it did NOT happen -- stops the script rather than running
code written on the assumption that it did. `trywait [/timeout:ms]` is the
polling form: it reports through $? and continues.

Examples

    event ready create /manual
    corunproc worker           # worker does: event ready wait
    event ready signal

Exit status

0       Operation succeeded (wait: signaled).
>0      Wait timeout, unknown name, or bad usage.

See also

mutex, semaphore, barrier, channel, sync, corunproc

exec back to top ↑

replace shell with command

Synopsis

    exec COMMAND [ARGS...]

Description

Replaces the current shell process with the specified command. The command runs in place of the shell - when the command exits, there is no shell to return to.

Options

    COMMAND         Command to execute.
    ARGS            Arguments for the command.

Examples

    exec notepad
        Replace shell with Notepad.

    exec cmd
        Replace shell with Windows cmd.exe.

    exec /usr/bin/bash
        Replace with another shell.

    exec python script.py
        Run Python script, exit when done.

Exit status

Does not return (shell is replaced).

Notes

No Return: exec does not return. The shell process is completely replaced by the new command. When that command exits, the window closes.

Use Cases: - Final command in a script - Switching to another shell - Wrapper scripts that launch another program - Reducing process overhead (no extra shell process)

Comparison with start: - exec: Replaces shell, no return - start: New window, shell continues

Resource Efficiency: exec is slightly more efficient than starting a child process because it doesn't keep the shell running.

Scripts: In scripts, commands after exec never run: exec myprogram echo "Never executed"

See also

start, source, exit

exit back to top ↑

exit the shell

Synopsis

    exit [CODE]

Description

Terminates the shell session. An optional exit code can be specified to return to the parent process or operating system.

In scripts, exit terminates script execution and returns the specified code.

Options

    CODE            Integer exit code (default: 0).
                    Convention:
                    0 = success
                    non-zero = error/failure

Examples

    exit
        Exit shell with code 0 (success).

    exit 0
        Explicitly exit with success.

    exit 1
        Exit with error code 1.

    # In a script:
    if ($result != "ok")
        exit 1
    endif
        Exit script on error condition.

Exit status

Returns the specified CODE or 0 if not specified.

Notes

Running Jobs: If background jobs are running, exit may warn you. Use 'jobs' to check for running jobs before exiting.

Scripts: In scripts, exit immediately terminates execution. No further commands are run.

Return vs Exit: In procedures, use 'return' instead of 'exit' to return control to the caller without terminating the shell.

See also

return, jobs, logout

false back to top ↑

return failure (documented with true)

Synopsis

    false

Description

Sets $status to 1 (failure). Documented alongside `true` and `nop` on a single page -- see `man true` for full details.

See also

true, nop, exit

fetch back to top ↑

transfer data from a URL (HTTP/HTTPS/FTP client)

Synopsis

    fetch [options] URL
    fetch /o:FILE URL
    fetch /I URL

Description

Transfers data from a URL to stdout (or a file), similar to curl or wget.

By default HTTP and HTTPS go through WinHTTP, which negotiates HTTP/2 or HTTP/1.1 with the server. To pin the protocol, use /http2 or /http3: these select cshw's own native client, which GUARANTEES the protocol rather than negotiating it -- nghttp2 over SChannel TLS for HTTP/2, and msquic + nghttp3 (QUIC/UDP) for HTTP/3. The protocol actually used is reported with /I or /v and is set in $result. ftp:// URLs are also supported (via WinINet).

Switches accept either /name or -name / --name form.

Options

    /o:FILE, /output:FILE
                    Write the response body to FILE instead of stdout.

    /O              Save to a file named after the URL's last path segment (e.g.
                    fetch /O https://host/file.zip writes file.zip). Errors if the
                    URL has no filename.

    /c, /continue   Resume a partial download (requires /o or /O). Sends a Range
                    request from the current file size and appends the rest; if the
                    file is already complete, nothing is downloaded.

    /I, /head       Print only the response headers (and the protocol used), no body.

    /v, /verbose    Verbose: print headers + protocol, then the body.

    /s, /silent, /q, /quiet
                    Suppress fetch's own error messages.

    /X:METHOD, /request:METHOD
                    HTTP method (GET, POST, PUT, DELETE, ...). Default GET.

    /d:DATA, /data:DATA
                    Send DATA as the request body (use with /X:POST). Sent as
                    application/x-www-form-urlencoded.

    /http2, /2      Force HTTP/2 using the native nghttp2 client over SChannel TLS
                    (ALPN "h2"). https only. Unlike the WinHTTP default, the
                    connection IS HTTP/2 or it fails -- it never silently downgrades.

    /http3, /3      Force HTTP/3 using the native msquic + nghttp3 client (QUIC over
                    UDP, ALPN "h3"). https only. The server must offer HTTP/3 on the
                    URL's port; there is no Alt-Svc-based upgrade from TCP.

    /k, /insecure, /no-check-certificate
                    Skip TLS certificate validation. For self-signed / local test
                    servers only -- never against real services (the certificate is
                    the only thing preventing a man-in-the-middle).

Result

$result is set to the protocol used: "HTTP/1.1", "HTTP/2", or "HTTP/3" (with
/http2 or /http3 this is the forced protocol; otherwise it is what WinHTTP
negotiated).

Examples

    fetch https://example.com
        Print the page to stdout.

    fetch /o:page.html https://example.com
        Save the response body to page.html.

    fetch /O https://example.com/archive.zip
        Save as archive.zip (filename taken from the URL).

    fetch /c /O https://example.com/big.iso
        Resume a partial big.iso download.

    fetch /I https://example.com
        Show response headers and the protocol used.

    fetch /X:POST /d:"name=value" https://api.example.com/submit
        POST a form body.

    fetch /http2 /I https://example.com
        Force HTTP/2 via the native client and show the headers.

    fetch /http3 /I https://cloudflare.com
        Force HTTP/3 (QUIC) via the native client.

    fetch /k https://localhost:8443/
        Fetch from a local server with a self-signed certificate.

Notes

The default (WinHTTP) path negotiates HTTP/2 or HTTP/1.1 and is best-effort -- WinHTTP's client-side HTTP/2 is not always selected even against an h2-capable server. When you need a specific protocol, use /http2 or /http3: those use cshw's native clients and guarantee it (nghttp2 for h2; msquic + nghttp3 for h3), the same libraries the cshw http.dll and quicsrv servers use. The native path requires nghttp2.dll / nghttp3.dll / msquic.dll beside cshw.exe; if they are absent only /http2 and /http3 are affected -- the default path still works.

Exit status

0       Success
>0      Error (bad URL, connection failure, HTTP/file error)

See also

ftpfetch, socket, tcpclient, hostname

fg back to top ↑

move job to foreground

Synopsis

    fg [%JOBID]

Description

Brings a background job to the foreground, making it the active process. If no job ID is specified, operates on the current job.

Options

    %JOBID          Job number (from jobs command).

Examples

    fg
        Bring current job to foreground.

    fg %1
        Bring job 1 to foreground.

    fg %2
        Bring job 2 to foreground.

Exit status

0       Success
1       No such job

Notes

Interaction: Once in foreground, you can interact with the process normally. Use Ctrl+Z to stop and background it again.

Wait for Completion: fg waits for the job to complete or be stopped before returning control to the shell.

See also

bg, jobs, kill, stop

file back to top ↑

identify file type

Synopsis

    file FILE
    file FILE...

Description

Determines file type by examining content, not just the extension. Uses "magic numbers" (byte patterns) to identify file formats.

Options

    FILE            One or more files to identify.

    -b, --brief     Don't show filename in output.
    -i, --mime      Output MIME type instead of description.
    -z              Try to look inside compressed files.

Examples

    file document.pdf
        # document.pdf: PDF document, version 1.4

    file image.png
        # image.png: PNG image data, 800 x 600, 8-bit/color RGBA

    file program.exe
        # program.exe: PE32+ executable (GUI) x86-64

    file unknown
        # unknown: ASCII text

    file mystery.dat
        # mystery.dat: Zip archive data, at least v2.0 to extract

    file -i document.pdf
        # document.pdf: application/pdf

    file *
        Identify all files in directory.

Exit status

0       Success
1       Error

Notes

Magic Numbers: Many file formats start with distinctive byte sequences: - PNG: 89 50 4E 47 0D 0A 1A 0A - PDF: 25 50 44 46 (% P D F) - ZIP: 50 4B 03 04 - EXE: 4D 5A (MZ) - JPEG: FF D8 FF

Extension Independence: file identifies by content, so renamed files are identified correctly: mv image.png image.txt file image.txt # Still identifies as PNG

Use Cases: - Verify file types before processing - Find misnamed files - Security analysis - Batch file organization

Unknown Files: For unrecognized formats, file reports basic type: - "data" for binary files - "ASCII text" or "UTF-8 text" for text

See also

hexdump, strings, peinfo

file-rename back to top ↑

rename files with a Perl-style expression

Synopsis

    file-rename [options] EXPRESSION FILE...

Description

Identical to `prename`. Both names are registered because perl-rename ships under both in the wild -- Debian packages it as `prename` and `file-rename` -- so a script written against either runs unmodified.

See `man prename` for the expression forms, the options, and why --perl is opt-in.

See also

prename, rename, mv

fileblob back to top ↑

encode a file into a one-line text blob

Synopsis

    fileblob <file>

Description

fileblob reads <file> and writes a single line of text -- a "blob" -- to standard output. The blob is the file's bytes base64-encoded behind a CSHWBLOB1 header that also records the original filename:

CSHWBLOB1:<original-name>:<base64-data>

Because the blob is plain text it can go wherever text can: captured into a shell variable, redirected to a .blob file, or pasted inline in a script -- a way to carry a binary asset (an icon, a small data file) as text. Decode it again with unfileblob.

Examples

    set logo = `fileblob icon.png`
        Hold a binary asset in a shell variable.

    fileblob icon.png > icon.blob
        Save the blob to a file for use later.

Exit status

0 on success; non-zero if the file cannot be read.

See also

unfileblob, base64

find back to top ↑

search for files in a directory tree

Synopsis

    find [path] -name PATTERN [filters...]
    find [path] [filters...]
    find PATTERN [dir] [/s] [filters...]

Description

Searches for files and directories matching a name pattern, optionally filtered by type, size, modification time and depth.

find accepts two operand orders, and tells them apart by whether the first operand is a directory that exists:

find . -name "*.txt"        Unix order: a path, then filters.
                            Recursive, like every other find.
find "*.txt" . /s           cshw's own order: the pattern first,
                            then the directory. NOT recursive
                            unless /s is given.

A lone directory operand is the Unix reading: `find src` lists everything under src. A lone pattern is cshw's: `find "*.log"` matches in the current directory only.

Every match prints on its own line, path included. Nothing matching is not an error; a search root that does not exist is.

Options

    path            Directory to search from (default: current dir).
                    Its presence turns recursion on.

    -name PATTERN   Match PATTERN (supports * and ? wildcards).
                    Matching is case-insensitive on Windows.

    -iname PATTERN  Same thing. Windows filename comparison is already
                    case-insensitive, so -iname is a synonym here
                    rather than a separate mode.

    -type TYPE      Filter by type:
                    f   Regular files only
                    d   Directories only

    -size [+|-]N    Find files by size:
                    N   Exactly N bytes
                    +N  Greater than N bytes
                    -N  Less than N bytes
                    Suffixes: c (bytes), k (KB), M (MB), G (GB)

    -mtime [+|-]N   Find by modification time (days):
                    N   Modified exactly N days ago
                    +N  Modified more than N days ago
                    -N  Modified less than N days ago

    -maxdepth N     Descend at most N directory levels.

    -mindepth N     Ignore matches shallower than level N.

    -delete         Delete each match after printing it.

    -print          No-op. cshw's find always prints; -print is accepted
                    so GNU-style command lines do not have to be edited.

    /s              Recurse. Only needed in the pattern-first order --
                    a path operand implies it.

    Anything else beginning with - or / is an error, not a silent
    no-op: a filter find does not implement must never be mistaken for
    one it honoured.

Examples

    find . -name "*.txt"
        Every .txt file under the current directory.

    find C:\Users -name "*.doc"
        Every .doc file under C:\Users.

    find . -type f -name "*.log"
        Only files (not directories) with a .log extension.

    find . -type d
        Only directories.

    find . -size +10M
        Files larger than 10 megabytes.

    find . -mtime -7
        Files modified in the last 7 days.

    find . -maxdepth 2 -name "*.exe"
        Search only 2 levels deep.

    find src
        Everything under src.

    find "*.log"
        Matches in the current directory only -- no recursion, because
        no path operand was given.

    find "*.tmp" . /s -mtime +30 -delete
        The pattern-first order: month-old temp files, deleted.

Exit status

0       The search ran (matches may or may not have been found).
1       The search root does not exist, or an unrecognized filter
        was given.

Notes

Quote your patterns: find . -name "*.txt" Without the quotes the shell expands *.txt against the current directory before find ever sees it, and find searches for whatever that happened to produce.

Wildcards: * Matches any sequence of characters ? Matches any single character

Performance: On very large trees, use -maxdepth to bound the walk.

Combining with other commands: find . -name "*.log" | grep error find . -name "*.bak" | wc -l

See also

dir, grep, where, which

fmt back to top ↑

reflow paragraphs to a width

Synopsis

    fmt [-w N] [FILE...]

Description

Fills paragraphs so that lines are as full as they can be without exceeding a width. With no FILE, reads standard input.

fmt REFLOWS: it joins the lines of a paragraph back together and re-breaks them at word boundaries, so ragged text comes out evenly filled. A blank line separates paragraphs and is preserved, so structure survives.

Options

    -w N            Fill to N columns. Default 72.
                    The historical form -N (e.g. -60) means the same thing.

Examples

    fmt notes.txt
        Reflow to the default 72 columns.

    fmt -w 60 notes.txt
        Narrower.

    fmt -w 65 letter.txt | pr -h "Draft" | lp
        Reflow, paginate, print.

Exit status

0       Success
1       A named file could not be opened

Notes

fmt versus fold: fold -w 20 cuts each line at 20 columns; short lines stay short fmt -w 20 joins the paragraph up and refills every line

Given three short lines, fold leaves three short lines and fmt merges them into one full one. Use fmt for prose, fold when line boundaries carry meaning and must not move.

Word longer than the width: A word that cannot fit is placed on a line of its own and allowed to overrun, rather than being split. fold -s makes the opposite choice.

Where this differs from GNU fmt: cshw fills GREEDILY -- each line takes as many words as fit within the width. GNU's fmt instead aims at a goal width of roughly 93% of the maximum and chooses breaks that minimise raggedness across the whole paragraph, so its lines come out shorter and more even. Measured on the same input at -w 30, GNU produced lines of 25, 27, 23 and 12 columns; cshw produces 30, 30 and 28.

Both honour the width as a hard maximum, and neither splits words. If you need output identical to GNU's, pipe through GNU fmt; if you need lines filled to the width you asked for, this is what you want.

See also

fold, nl, pr, lp

fold back to top ↑

wrap long lines to a fixed width

Synopsis

    fold [-w N] [-s] [FILE...]

Description

Breaks each input line so that no output line is longer than a given width. With no FILE, reads standard input.

fold CUTS; it does not reflow. Every input line is broken independently, and short lines are left exactly as they are. When you want ragged text filled out into even paragraphs, that is fmt.

Options

    -w N            Wrap at N columns. Default 80.
                    The historical form -N (e.g. -20) means the same thing.
    -s              Break at a space, so words are not split. If a single
                    word is longer than the width it is still broken -- it
                    has to go somewhere.
    -b              Accepted and ignored. Counts bytes rather than columns
                    in other implementations; cshw counts characters.

Examples

    fold -w 40 notes.txt
        Hard-break every line at 40 columns.

    fold -s -w 40 notes.txt
        Break at spaces instead, so words stay whole.

    cat report.txt | fold -s -w 72 | lp
        Wrap for a printer that cannot handle long lines.

Exit status

0       Success
1       A named file could not be opened

Notes

fold versus fmt: fold -w 20 cuts each line at 20 columns, leaving short lines short fmt -w 20 joins the text back together and refills to 20 columns

Use fold when line boundaries matter and must not move, such as fixed-record data. Use fmt for prose.

See also

fmt, nl, pr, cut

ftpfetch back to top ↑

FTP file transfer client

Synopsis

    ftpfetch URL
    ftpfetch [options] URL

Description

Downloads files from FTP servers. Supports anonymous and authenticated FTP transfers.

Options

    URL             FTP URL to download from.
                    Format: ftp://[user:pass@]host/path

    -o FILE         Output filename (default: derived from URL).
    -u USER         FTP username.
    -p PASS         FTP password.
    -P PORT         FTP port (default: 21).
    -v, --verbose   Show transfer progress.
    --passive       Use passive mode (default).
    --active        Use active mode.

Examples

    ftpfetch ftp://ftp.example.com/pub/file.zip
        Anonymous download.

    ftpfetch -o download.zip ftp://ftp.example.com/file.zip
        Download with specific output name.

    ftpfetch -u myuser -p mypass ftp://ftp.example.com/private/data.txt
        Authenticated download.

    ftpfetch ftp://user:pass@ftp.example.com/file.txt
        Credentials in URL.

    ftpfetch -v ftp://ftp.example.com/large.iso
        Verbose mode with progress.

Exit status

0       Success
1       Connection error
2       Authentication failed
3       File not found
4       Transfer error

Notes

Anonymous FTP: Without credentials, ftpfetch uses anonymous login (typically "anonymous" with email as password).

Passive vs Active: - Passive mode (default): Works through firewalls - Active mode: May be blocked by firewalls

URL Format: ftp://ftp.example.com/pub/file.txt Anonymous ftp://user:pass@ftp.example.com/file Authenticated

Binary vs ASCII: ftpfetch uses binary mode by default, appropriate for most files.

Security: FTP transmits credentials in plain text. For secure transfers, consider SFTP or HTTPS instead.

Large Files: ftpfetch supports large files and shows progress in verbose mode.

See also

fetch, copy

genai back to top ↑

interact with AI language models

Synopsis

    genai register PROVIDER API_KEY [options]
    genai list
    genai remove NAME
    genai default NAME
    genai complete PROMPT
    genai chat
    genai analyze FILE

Description

Interface to generative AI language models including OpenAI (GPT) and Anthropic (Claude). The genai command allows you to register AI providers, send prompts, have conversations, and analyze files using AI.

This is a powerful tool for code generation, text analysis, problem solving, and interactive AI assistance directly from the shell.

Options

    Subcommands:

    register PROVIDER API_KEY [options]
        Register a new AI provider.
        PROVIDER: openai, anthropic
        API_KEY: Your API key for the provider
        Options:
            --model MODEL       Model to use (e.g., gpt-4, claude-3-opus)
            --name NAME         Custom name for this configuration
            --default           Set as default provider

    list
        Display all registered AI providers.

    remove NAME
        Remove a registered provider configuration.

    default NAME
        Set the default AI provider.

    complete PROMPT
        Send a prompt and get a completion response.
        Also accepts piped input.

    chat
        Start an interactive chat session.
        Type 'exit' or 'quit' to end.

    analyze FILE
        Send file contents to AI for analysis.

Examples

    genai register openai sk-xxx123 --model gpt-4 --default
        Register OpenAI with GPT-4 as the default.

    genai register anthropic sk-ant-xxx --model claude-3-opus --name claude
        Register Anthropic's Claude as 'claude'.

    genai list
        Show all registered AI providers.

    genai default claude
        Switch default to the 'claude' configuration.

    genai complete "Write a Python hello world program"
        Get an AI-generated response.

    genai complete "Explain this code:" < script.py
        Pipe file content with a prompt.

    type error.log | genai complete "What caused this error?"
        Analyze log file with AI.

    genai chat
        Start interactive conversation mode.

    genai analyze main.cpp
        Have AI analyze a source file.

    echo "Translate to French: Hello" | genai complete
        Use piped input as the prompt.

Exit status

0       Success
1       Provider not found or not configured
2       API error (invalid key, rate limit, etc.)
3       Network error
4       Invalid arguments

Environment

OPENAI_API_KEY      Default API key for OpenAI
ANTHROPIC_API_KEY   Default API key for Anthropic

Files

    %APPDATA%\cshw\genai.json    Stored provider configurations

Notes

API Keys: Keep your API keys secure. They are stored in the configuration file. Consider using environment variables for sensitive keys.

Rate Limits: AI providers have rate limits. If you exceed them, you'll receive an error. Wait before retrying.

Costs: API calls may incur costs depending on your provider plan. Monitor your usage on the provider's dashboard.

Model Selection: Different models have different capabilities and costs: - gpt-4: Most capable OpenAI model, higher cost - gpt-3.5-turbo: Fast and economical - claude-3-opus: Most capable Anthropic model - claude-3-sonnet: Balanced performance/cost

Token Limits: Each model has maximum token limits. Very long prompts or files may be truncated or cause errors.

Interactive Chat: In chat mode, context is maintained within the session. The AI remembers previous messages in the conversation.

See also

type, echo, fetch

glob back to top ↑

expand filename patterns

Synopsis

    glob PATTERN
    glob PATTERN...

Description

Expands wildcard patterns into matching filenames. Useful for testing patterns before using them in commands, or in scripts that need explicit filename lists.

Options

    PATTERN         Wildcard pattern to expand.

    Wildcards:
    *               Match any characters (including none)
    ?               Match exactly one character
    [abc]           Match any character in brackets
    [a-z]           Match character range
    [!abc]          Match any character NOT in brackets

Examples

    glob *.txt
        List all .txt files.

    glob src/*.cpp
        List C++ files in src directory.

    glob [A-Z]*.doc
        Files starting with uppercase letter.

    glob ???.txt
        Three-character names with .txt extension.

    glob **/*.h
        Recursively find header files.

    glob file[0-9].dat
        Match file0.dat through file9.dat.

    glob *.[ch]
        Match .c and .h files.

    glob [!._]*
        Files not starting with . or _

Exit status

0       Matches found
1       No matches

Notes

No Matches: On a COMMAND LINE, a pattern that matches nothing is an error, as in csh: the shell reports "PATTERN: No match.", runs nothing, and sets the status to 1. That is what stops `rm *.tmp` from being handed a literal asterisk in a directory with no .tmp files.

set nonomatch    pass the unmatched word through as typed instead
set noglob       turn filename substitution off altogether

An unterminated `[` is not a pattern at all -- `echo [` prints a bracket rather than reporting no match -- because a character class needs a closing `]` to be one. The target of an assignment is not a pattern either, so `set list[2] = x` addresses element 2 rather than looking for a file called list[2].

Escaping: To match literal wildcard characters, escape them: glob file\*.txt # Matches "file*.txt" literally

Hidden Files: By default, patterns don't match files starting with '.' Use .* to explicitly match hidden files.

Directory Patterns: glob can expand directories too: glob */ # All subdirectories

Recursive Patterns: Use **/ for recursive matching: glob **/*.log # All .log files in all subdirectories

Use in Scripts: set files=$(glob *.txt) foreach f ($files) echo "Processing $f" endforeach

See also

find, dir, ls

grep back to top ↑

search for patterns in files

Synopsis

    grep [options] PATTERN [FILE...]
    grep [options] PATTERN

Description

Searches for PATTERN in each FILE or standard input. By default, grep prints the matching lines. PATTERN is a regular expression using PCRE2 (Perl Compatible Regular Expressions) syntax when available, falling back to std::wregex otherwise.

grep is one of the most powerful text-processing tools in CSHW, supporting both simple string searches and complex pattern matching with full regex capabilities including lookahead, lookbehind, and Unicode support.

When reading from standard input (piped data), grep processes each line and outputs those matching the pattern.

Options

    PATTERN         The regular expression to search for.
    FILE...         One or more files to search. If omitted, reads stdin.

    -i, --ignore-case
                    Perform case-insensitive matching.

    -v, --invert-match
                    Invert the sense of matching - select non-matching lines.

    -n, --line-number
                    Prefix each output line with its line number in the file.

    -h, --no-filename
                    Suppress the prefixing of filenames on output when
                    searching multiple files.

    -r, --recursive
                    Recursively search subdirectories.

    -l, --files-with-matches
                    Only print filenames containing matches (not the lines).

    -c, --count
                    Only print a count of matching lines per file.

    -o, --only-matching
                    Print only the part of each line that matched, one match
                    per line, instead of the whole line. Use it to pull a
                    field out of unstructured output. -v prints nothing (a
                    line selected by NOT matching has no matched text), and
                    -c wins over -o because "how many lines" and "show me
                    each match" are different questions.

    -q, --quiet, --silent
                    Print nothing at all and stop at the first match. Exists
                    for its exit status: if (grep -q PAT file) then ...

    -H, --with-filename
                    Always prefix output with the filename. The counterpart
                    to -h; the prefix otherwise appears only when there is
                    more than one file to disambiguate.

    -F, --fixed-strings
                    Treat PATTERN as a literal string, not a regex.

    -w, --word-regexp
                    Match only whole words (the pattern is anchored at a
                    word boundary on both sides).

    -E, --extended-regexp
                    Accepted and ignored: cshw's grep is already extended.

    --pcre2         Use the PCRE2 engine explicitly, for lookahead,
                    lookbehind and the rest of the fuller dialect.

    Short flags bundle: -ci, -rl, -oE and so on. An unrecognised flag is an
    error (exit 2), never a pattern.

Examples

    grep error log.txt
        Find lines containing "error" in log.txt.

    grep -i ERROR log.txt
        Case-insensitive search for "error".

    grep -n "TODO" *.cpp
        Show line numbers for TODO comments in C++ files.

    grep -r "password" .
        Recursively search for "password" in current directory tree.

    grep -v "^#" config.txt
        Show lines NOT starting with # (non-comments).

    grep "^\s*$" file.txt
        Find empty or whitespace-only lines.

    type log.txt | grep -i warning
        Search piped input for warnings (case-insensitive).

    grep "[0-9]{3}-[0-9]{4}" contacts.txt
        Find phone number patterns (###-####).

    grep -rn "class\s+\w+" src/
        Find class definitions in source directory.

    dir /b | grep "\.txt$"
        Filter dir output to show only .txt files.

    grep "^(GET|POST)" access.log
        Find HTTP GET or POST requests in log.

    grep -l "main" *.cpp
        List .cpp files containing "main".

    grep -oE "[0-9]+" version.txt
        Print just the numbers, one per line, not the lines they sit on.

    grep -q "ERROR" app.log && echo "something went wrong"
        Test for a match without printing anything.

Exit status

0       One or more matches were found
1       No matches were found
2       Error occurred (file not found, invalid regex, etc.)

Notes

PCRE2 Regular Expression Quick Reference:

.       Any character (except newline)
^       Start of line
$       End of line
*       Zero or more of preceding
+       One or more of preceding
?       Zero or one of preceding
[abc]   Character class (a, b, or c)
[^abc]  Negated class (not a, b, or c)
[a-z]   Character range
\d      Digit [0-9]
\w      Word character [a-zA-Z0-9_]
\s      Whitespace
\b      Word boundary
(x|y)   Alternation (x or y)
(...)   Grouping
{n}     Exactly n occurrences
{n,m}   Between n and m occurrences
(?=...) Positive lookahead
(?!...) Negative lookahead
(?i)    Case-insensitive mode (inline)

CSHW's grep uses PCRE2 with JIT compilation for optimal performance on large files. The JIT compiler provides near-native speed for complex patterns.

See also

find, type, wc, sort, uniq

hash back to top ↑

create or manipulate an associative array (hash) variable

Synopsis

    hash <name>
    hash <name> <key>=<value> ...
    hash set  <name> <key> <value>
    hash get  <name> <key>
    hash has  <name> <key>
    hash keys <name>
    hash list <name>
    hash size <name>

Description

Creates and manipulates string-keyed hash variables. The bare form declares: `hash config` makes an empty hash, and trailing `key=value` pairs seed it.

Everything else is a subcommand. Elements are read with `$name[key]` -- the same bracket syntax `array` uses, because the two differ in what goes inside the brackets, not in the punctuation. There is no brace form: `$config{name}` is not a hash reference, it is `$config` followed by the literal text `{name}`.

`get`, `has` and `size` also publish their answer in `$result`, so a script can use it without capturing output. `hash has` additionally sets the exit status -- 0 when the key is present, 1 when it is not -- so it reads naturally in a conditional.

Options

    <name>          Hash name. Same rules as scalar variable names.
    <key>=<value>   Optional initial entries for the declaration form.

    set NAME KEY VALUE
                    Store VALUE under KEY, creating NAME if needed.
    get NAME KEY    Print the value for KEY (empty if absent) and set
                    $result to it.
    has NAME KEY    Print 1 or 0, set $result to the same, and set the
                    exit status to 0 (present) or 1 (absent).
    keys NAME       Print every key, one per line, in sorted order.
    list NAME       Print every entry as "key = value", one per line.
    size NAME       Print the number of entries and set $result to it.

Examples

    hash users alice=admin bob=user
    echo "alice is $users[alice]"

    hash settings
    hash set settings theme dark
    hash set settings font Consolas
    hash list settings

    hash has settings theme
    if ($status == 0) then
        echo "theme is $settings[theme]"
    endif

    hash size settings
    echo "$result entries"

Exit status

0       Hash declared / updated, or (for `has`) the key was present.
1       Bad name, malformed key=value pair, or (for `has`) the key
        was absent.

Notes

Declaration vs subcommand: The first operand is matched against the subcommand names first, so the bare declaration form cannot name a hash `set`, `get`, `has`, `keys`, `list` or `size`. `hash set set KEY VALUE` still reaches such a hash -- only the shorthand is unavailable for those six names.

Keys are sorted: Entries live in a sorted map, so `hash keys` and `hash list` print in key order, not insertion order.

Re-declaring is safe: `hash config` on an existing hash keeps its contents, so a sourced script that declares its hashes at the top can be sourced twice.

For integer-indexed arrays, see `array`. The two styles are distinct: `array` indexes by position, `hash` by string key. Both read back with $name[...].

See also

array, set, unset, declare

hashstat back to top ↑

display command hash table statistics

Synopsis

    hashstat

Description

Displays statistics about the command hash table, including the number of entries, hits, misses, and efficiency information.

Examples

    hashstat
        # Hash table statistics:
        # Entries: 45
        # Hits: 234
        # Misses: 12
        # Hit rate: 95.1%

Exit status

0       Success

Notes

Statistics Shown: - Number of cached command paths - Cache hit count (found in hash) - Cache miss count (required PATH search) - Hit rate percentage

Performance Tuning: High miss rates might indicate: - Commands not in expected locations - Frequent PATH changes - Need to run rehash

Debugging: Use hashstat to understand shell command lookup performance.

See also

rehash, unhash, which

head back to top ↑

output the first part of files

Synopsis

    head [options] FILE
    head -n COUNT FILE
    command | head [options]

Description

Outputs the first part of files or piped input. By default, prints the first 10 lines. Useful for previewing files or limiting output.

Options

    FILE            File to read from.

    -n COUNT        Output the first COUNT lines (default: 10).
    -COUNT          Shorthand for -n COUNT (e.g., -20).

    -c COUNT        Output the first COUNT bytes instead of lines.

Examples

    head file.txt
        Display first 10 lines of file.txt.

    head -n 20 log.txt
        Display first 20 lines.

    head -50 data.csv
        Display first 50 lines (shorthand).

    dir /s | head -n 30
        Show first 30 lines of dir output.

    head -c 100 binary.dat
        Show first 100 bytes.

    type largefile.txt | head
        Preview beginning of a large file.

Exit status

0       Success
1       File not found
2       Read error

Notes

Default Lines: Without -n, head outputs 10 lines by default.

Binary Files: Use -c for binary files where line concepts don't apply.

Piping: head is commonly used at the end of a pipeline to limit output: find . -name "*.log" | head -n 5

See also

tail, type, wc

help back to top ↑

display command help

Synopsis

    help
    help COMMAND

Description

Displays brief help information for shell commands. Without arguments, lists all available built-in commands. With a command name, shows usage syntax for that command.

Options

    COMMAND         Command to get help for.

Examples

    help
        List all built-in commands.

    help cd
        Show brief help for cd command.

    help grep
        Show brief help for grep command.

Exit status

0       Success
1       Command not found

Notes

help vs man: - help: Brief usage summary (one or two lines) - man: Comprehensive documentation with examples

Quick Reference: Use help for quick syntax reminders: help tar # tar -c|-x|-t [-z] [-v] -f ARCHIVE [FILES...]

Finding Commands: 'help' without arguments shows all commands, useful for discovering available functionality.

Command Categories: Built-in commands cover: - File operations (dir, copy, del, mv, type) - Navigation (cd, pushd, popd, pwd) - Variables (set, unset, setenv) - Job control (jobs, bg, fg, kill) - And many more

See also

man

hexdump back to top ↑

display file contents in hexadecimal

Synopsis

    hexdump [options] FILE
    command | hexdump [options]

Description

Displays file contents in hexadecimal format with optional ASCII representation. Essential for examining binary files, debugging data formats, and analyzing file structures.

Options

    FILE            File to display.

    -C              Canonical format: hex + ASCII (most common).
    -n LENGTH       Display only first LENGTH bytes.
    -s OFFSET       Skip OFFSET bytes from start.
    -v              Display all data (don't suppress duplicate lines).

Examples

    hexdump -C file.bin
        Display file in canonical hex+ASCII format.

    hexdump -C -n 256 program.exe
        Show first 256 bytes of executable.

    hexdump -C -s 1024 -n 512 file.dat
        Show 512 bytes starting at offset 1024.

    echo "Hello" | hexdump -C
        See hex representation of text.

    hexdump -C image.png | head -20
        Preview beginning of PNG file.

Exit status

0       Success
1       File not found
2       Read error

Notes

Output Format (Canonical -C): 00000000 48 65 6c 6c 6f 20 57 6f 72 6c 64 0a |Hello World.| OFFSET HEX BYTES (16 per line) ASCII

Reading Hex: - Each hex pair represents one byte (00-FF) - ASCII column shows printable characters - Non-printable bytes shown as '.'

File Signatures: Many file formats have distinctive headers ("magic numbers"): - PNG: 89 50 4E 47 0D 0A 1A 0A - PDF: 25 50 44 46 (% P D F) - EXE: 4D 5A (MZ) - ZIP: 50 4B 03 04

See also

base64, strings, file, type

history back to top ↑

display command history

Synopsis

    history
    history [N]
    history -c

Description

Displays the list of previously executed commands. CSHW maintains a history of commands entered during the current session and optionally across sessions if persistence is enabled.

The history command is invaluable for recalling previous commands, understanding what operations were performed, and repeating or modifying past commands.

Options

    N               Display only the last N commands.

    -c, --clear     Clear the command history.

Examples

    history
        Display all commands in history.

    history 20
        Display the last 20 commands.

    history -c
        Clear all command history.

Exit status

0       Success

Notes

$histchars: The character that introduces a history reference, replacing `!`:

set histchars = ","      then  ,,  repeats the previous command

csh takes a two-character value, the second for `^old^new` quick substitution. Only the first is honoured here, because quick substitution is not implemented -- accepting the value and applying half of it silently would be worse than saying so.

History substitution happens at the interactive prompt only. A `!` in a script file is literal, whatever histchars says.

History Navigation: Use the up/down arrow keys at the command prompt to navigate through previous commands.

History Size: The shell maintains a configurable maximum number of history entries. Older entries are removed when the limit is reached.

History Persistence: History is saved to %APPDATA%\cshw\history and restored on shell startup. Use the history_max shell variable to configure the maximum number of entries persisted.

Command Recall: Previous commands can be recalled and edited before re-execution using the arrow keys.

Duplicate Handling: Consecutive duplicate commands may be stored only once to keep the history clean.

See also

alias, set

hostname back to top ↑

display the system hostname

Synopsis

    hostname [options]

Description

Displays the computer's network hostname. By default, shows the NetBIOS name. Options allow retrieving the DNS hostname or fully qualified domain name (FQDN).

Options

    -f, --fqdn    Display fully qualified domain name (e.g., host.domain.com)
    -d, --dns     Display DNS hostname

Examples

    hostname
        MYCOMPUTER

    hostname -f
        mycomputer.corp.example.com

    hostname -d
        mycomputer

Notes

This command displays the hostname but cannot change it. To change the hostname on Windows, use: - System Properties > Computer Name - PowerShell: Rename-Computer -NewName "NewName" - Control Panel: sysdm.cpl

The difference between name types: - NetBIOS name: Legacy Windows network name (up to 15 characters) - DNS hostname: Modern hostname used by DNS - FQDN: Complete DNS name including domain suffix

See also

uname, whoami, winver

install back to top ↑

install cshw onto the system

Synopsis

    install [path] [/user]

Description

Copies cshw.exe and its supporting files (man pages, runtime DLLs) to an install location, then updates PATH so `cshw` is invocable by name from any prompt.

By default the install is system-wide (under Program Files, writes HKLM PATH) and requires admin. With /user, the install is per-user (under %LOCALAPPDATA%, writes HKCU PATH) and runs without elevation.

Options

    path        Optional explicit install directory. If omitted, uses
                a sensible default based on whether /user is set.
    /user       Install per-user under %LOCALAPPDATA%. No admin needed.
                Modifies only HKCU PATH.

Examples

    install
        System-wide install to Program Files. Requires admin.

    install /user
        Per-user install to %LOCALAPPDATA%\Tropibyte\cshw.

    install "C:\tools\cshw"
        System-wide install to an explicit directory.

Exit status

0       Install succeeded.
1       Permission denied (not running elevated for a system
        install) or copy/registry write failure.

Notes

The Inno Setup installer (cshw-setup-X.Y.Z.exe) is the recommended distribution mechanism for end users -- it adds file associations, Windows Terminal integration, and an uninstaller. This `install` command is the lightweight in-shell alternative for scripted setups or developer workflows.

See also

sudo, rcl

isWindows back to top ↑

test whether the shell is running on Windows

Synopsis

    isWindows
    iswindows

Description

A platform predicate: reports whether the running shell is on Windows, so a portable csh/tcsh script can take one path on Windows and another on Unix/Linux. On cshw -- a native Windows shell -- it is effectively always true: it prints 1, sets the $isWindows variable and $result to 1, and succeeds (exit status 0). A csh/tcsh on Unix or Linux has no Windows to report, so the equivalent test is false there; guarding Windows-specific code with isWindows lets the same script do the right thing on each platform. Both spellings work.

Usable two ways: as a truth value in a csh `if (...)` test (the value is 1), and as an exit-status predicate for `&&` / `||` chaining (success on Windows).

Examples

    if (isWindows) then
        set sep = ";"          # Windows PATH separator
    else
        set sep = ":"          # Unix / Linux
    endif

    isWindows && echo "on Windows"

Exit status

0       On Windows -- the true result (and the value 1 is printed and stored
        in $isWindows / $result). On cshw this is always the case.
1       On a non-Windows shell -- the false result. cshw never reports this,
        since it only runs on Windows.

Notes

Because cshw only runs on Windows, isWindows never reports false here; it exists so cross-platform csh/tcsh scripts stay clean.

See also

winapi, winver, uname

jobs back to top ↑

display status of background jobs

Synopsis

    jobs
    jobs [options]

Description

Displays the status of jobs that have been started in the background. Each job is identified by a job number and shows its current state (running, stopped, completed) along with the command that started it.

Job control allows you to run multiple commands simultaneously, switching between foreground and background execution as needed.

Options

    -l              Long format - include process IDs.
    -p              Print only process IDs.
    -r              Display only running jobs.
    -s              Display only stopped jobs.

Examples

    jobs
        List all background jobs.

    jobs -l
        List jobs with process IDs.

    jobs -r
        Show only currently running jobs.

Exit status

0       Success

Notes

Job States: RUNNING - Job is currently executing STOPPED - Job has been suspended (Ctrl+Z) COMPLETED - Job has finished execution

Job Numbers: Jobs are assigned sequential numbers starting from 1. These numbers can be used with fg, bg, kill, and other job control commands.

Starting Background Jobs: To start a command in the background, append & to the command line: longprocess.exe &

Current and Previous Jobs: The most recently backgrounded job is the "current" job (+). The previously backgrounded job is the "previous" job (-).

See also

fg, bg, kill, stop, processlist

kad back to top ↑

kill process and secure-delete its executable (alias for killanddel)

Synopsis

    kad <pid_or_name>

Description

`kad` is identical to `killanddel`. See `man killanddel` for full documentation.

See also

killanddel, kill, processlist

kill back to top ↑

terminate processes

Synopsis

    kill PID
    kill -9 PID
    kill %JOBID

Description

Terminates a process by its process ID (PID) or job number. By default, kill attempts a graceful termination, but can forcefully terminate processes that don't respond.

kill is essential for managing runaway processes, stopping hung programs, and controlling background jobs.

Options

    PID             Process ID to terminate (numeric).

    %JOBID          Job number from jobs command (prefixed with %).

    -9, -KILL       Forcefully terminate (no cleanup allowed).

    -15, -TERM      Request graceful termination (default).

    /f              Force termination (same as -9).

    /t              Terminate process tree (include child processes).

Examples

    kill 1234
        Terminate process with PID 1234.

    kill -9 1234
        Forcefully terminate process 1234.

    kill %1
        Terminate job number 1.

    kill /f /t 1234
        Force-kill process 1234 and all its children.

    processlist | grep notepad
        # Find notepad's PID, then:
    kill 5678
        Terminate notepad process.

Exit status

0       Success - process terminated
1       Process not found
2       Access denied (need administrator privileges)
3       Invalid argument

Notes

Process Trees: Some processes spawn child processes. Use /t to terminate the entire process tree, not just the parent.

Access Rights: You can only kill processes you own, unless running as Administrator. System processes may require elevated privileges.

Graceful vs Forced: Without -9, kill sends a termination request allowing the process to clean up (save files, release resources). With -9, the process is immediately terminated with no cleanup.

Finding PIDs: Use 'processlist' or 'ps' to find process IDs, or use Task Manager.

Hung Processes: If a process doesn't respond to normal kill, use -9 to force termination.

See also

processlist, jobs, bg, fg, killanddel

killanddel back to top ↑

kill processes and securely delete executables

Synopsis

    killanddel [options] EXECUTABLE_PATH
    kad [options] EXECUTABLE_PATH

Description

Aliases: kad

Terminates all processes running a specified executable and securely deletes the file. Designed for removing malware that respawns quickly after deletion.

The command performs these steps: 1. Find all processes running the executable 2. Forcefully terminate those processes 3. Open file with exclusive access (prevent respawn) 4. Overwrite file contents with zeros 5. Delete the file

Options

    EXECUTABLE_PATH Path to the executable to kill and delete.

    /v, /verbose    Show detailed progress.
    /a, /ancestors  Show process ancestry (parent, grandparent).
    /r:N, /recurse:N
                    Also kill N levels of ancestor processes.
    /admin          Run with elevated Administrator privileges.
    /f, /force      Don't prompt for confirmation.
    /dry            Dry run - show actions without performing them.

Examples

    killanddel C:\temp\malware.exe
        Kill process and delete file.

    kad C:\temp\malware.exe
        Short form of killanddel.

    kad /v /a C:\temp\malware.exe
        Verbose output with ancestry display.

    kad /r:1 C:\temp\malware.exe
        Also kill the parent process.

    kad /dry C:\temp\suspicious.exe
        Preview what would happen.

    kad /admin C:\temp\malware.exe
        Run as Administrator for system-level access.

Exit status

0       Success - process killed and file deleted
1       File not found
2       Access denied (may need /admin)
3       Process termination failed
4       File deletion failed

Notes

Secure Deletion: Before deleting, the file is overwritten with zeros. This prevents simple file recovery tools from retrieving the original content.

Process Ancestry: The /a flag shows the process tree, helpful for identifying if malware has spawned from or infected another process.

Recursive Killing: /r:1 kills the malware's parent process. /r:2 kills parent and grandparent. Use carefully - you may kill legitimate processes.

Administrator Rights: Many malware processes run with elevated privileges. Use /admin to ensure you can terminate them.

Respawn Prevention: By opening the file exclusively before killing processes, killanddel prevents watchdog processes from respawning the malware.

Dry Run: Always use /dry first on unfamiliar malware to see what will happen before actually killing processes.

See also

kill, processlist, del

lc back to top ↑

count lines in files

Synopsis

    lc FILE
    lc PATTERN
    lc [/s] [/q] PATTERN[,PATTERN,...]
    lc [/s] [/q] DIR\PATTERN[,PATTERN,...]
    linecount [options] PATTERN...

Description

Counts the number of lines in files matching the specified pattern(s). Supports wildcards, multiple patterns, and recursive directory traversal. This is useful for quickly determining the size of a codebase or project.

When counting multiple files, displays the line count for each file followed by a summary showing total lines and file count.

The command name 'linecount' is an alias for 'lc'.

Options

    FILE            Single file to count lines in.

    PATTERN         Wildcard pattern (e.g., *.cpp, *.h, file?.txt).
                    Supports * (match any characters) and ? (match
                    single character).

    /s, -s, -r, --recursive
                    Recurse into subdirectories. Without this flag,
                    only files in the specified directory are counted.

    /q, -q, --quiet
                    Quiet mode. Only display the final total, not
                    individual file counts. Useful for scripts.

    Multiple patterns can be specified:
    - Comma-separated: *.cpp,*.h,*.c
    - As separate arguments: *.cpp *.h *.c (if shell supports)

Examples

    lc readme.txt
        Count lines in a single file.

    lc *.cpp
        Count lines in all .cpp files in current directory.

    lc /s *.cpp
        Count lines in all .cpp files, including subdirectories.

    lc /s *.cpp,*.h
        Count lines in all C++ source and header files recursively.

    lc /s /q *.c,*.h
        Quietly count all C files recursively (only show total).

    lc src\*.cpp
        Count lines in .cpp files in the src subdirectory.

    lc /s src\*.cpp,*.h,*.c
        Count C/C++ files in src directory tree.

    lc /s *.cpp,*.h,*.c,*.rc,*.vcxproj
        Count all Visual Studio C++ project source files.

    linecount /s *.py
        Count Python files recursively (using alias).

Exit status

0       Success
1       Syntax error or no files found

Notes

Codebase Size Estimation: Use lc to get accurate line counts for your project instead of guessing. Example for a typical C++ Visual Studio project:

lc /s *.cpp,*.h,*.c,*.rc,*.vcxproj,*.props

This counts all source files, resource files, and project files.

Pattern Matching: Patterns are case-insensitive on Windows. The following wildcards are supported: * Match zero or more characters ? Match exactly one character

Examples: *.cpp All files ending in .cpp test*.h Header files starting with "test" file?.txt file1.txt, fileA.txt, but not file10.txt

Performance: For large codebases, consider using /q (quiet) mode to reduce output overhead. The line counting itself is efficient, reading files line by line without loading entire files into memory.

Binary Files: Binary files will be counted but may report inaccurate line counts since they don't contain proper line endings. For best results, use patterns that match only text files.

Comparison with wc: - wc: UNIX-style word count for single file (lines, words, bytes) - lc: Line count optimized for multiple files with patterns

Empty Files: Empty files are included in the file count but contribute 0 lines.

See also

wc, find, dir, grep

library back to top ↑

load CSHW script as procedure library

Synopsis

    library FILE
    library FILE...

Description

Loads a CSHW script file and registers all procedures defined in it as available commands. This allows you to create reusable procedure libraries that can be loaded on demand.

Options

    FILE            Script file(s) containing procedure definitions.

Examples

    library utils.csh
        Load procedures from utils.csh.

    library lib/math.csh lib/string.csh
        Load multiple libraries.

    # File: mylib.csh
    proc greet(name)
        echo "Hello, $name!"
    endproc

    proc add(a, b)
        return ($a + $b)
    endproc

    # Then:
    library mylib.csh
    greet "World"
    set result=$(add 5 3)
        # result = 8

Exit status

0       Success
1       File not found
2       Syntax error in library

Notes

Procedure Registration: All 'proc' definitions in the file become available as commands after loading. They're registered in the global procedure registry.

Load Order: Libraries are loaded in order. Later definitions override earlier ones with the same name.

Dependencies: If a library depends on other libraries, load dependencies first: library base.csh library extended.csh # May use procs from base.csh

vs source: - library: Registers procedures for later use - source: Executes commands immediately

Best Practices: - Libraries should only contain procedure definitions - Use descriptive procedure names - Document procedures with comments - Group related procedures in one file

Reloading: Loading the same library again updates procedure definitions.

See also

source, proc, call

limit back to top ↑

display resource limits

Synopsis

    limit
    limit RESOURCE

Description

Displays the resource limits in effect for the shell, together with the current process's resource usage and system-wide memory figures.

LIMITS ARE READ-ONLY HERE. tcsh's `limit RESOURCE VALUE` form is accepted at the command line and refused with a message naming the resource, because Windows has no per-process rlimit for the shell to lower. Earlier versions of this page showed `limit filesize 100m` and `limit cputime 60` as working examples. They were not; both report "cannot be set on Windows" and exit 1.

With no argument, limit prints every resource, then this process's usage, then system memory. With a resource name, it prints that one line.

Options

    RESOURCE        Resource to report:
                    cputime      CPU time
                    filesize     Maximum file size
                    datasize     Data segment size
                    stacksize    Stack size (from the PE header)
                    coredumpsize Core dump size
                    memoryuse    Current working set
                    vmemoryuse   Virtual address space
                    descriptors  Max open file descriptors (CRT limit)
                    concurrency  Logical processors available
                    maxproc      Process count limit

Examples

    limit
        Display all limits, this process's usage, and system memory.

    limit filesize
        Display the file size limit alone.

    limit descriptors
        How many file descriptors the CRT will hand out.

    limit stacksize
        The reserved stack size for this image.

Exit status

0       Reported successfully.
1       Unknown resource name, or a value was supplied (limits
        cannot be set).

Notes

Why read-only: UNIX rlimits are a per-process kernel facility with no Windows equivalent a shell can apply to itself. Windows constrains processes with Job Objects, which are assigned from outside and govern a whole job rather than one process lowering its own ceiling. Accepting a limit cshw cannot enforce would be worse than declining to set it.

Bounding a child: To cap what a program may consume, launch it inside a Job Object rather than expecting `limit` to change anything the shell passes down.

unlimit: `unlimit` exists as a companion and likewise removes nothing; it prints where these figures come from.

Which numbers are measured: memoryuse and vmemoryuse come from this process. descriptors is the CRT's table size. concurrency is the logical processor count. stacksize is the reserve in the PE header. cputime, filesize, coredumpsize and maxproc report "unlimited" because nothing in Windows limits them for an ordinary process.

Inherited limits: Child processes inherit the environment, not a limit set -- there is no limit set to inherit.

See also

unlimit, nice, time

linecount back to top ↑

count lines in files (alias for lc)

Synopsis

    linecount FILE
    linecount [/s] [/q] PATTERN[,PATTERN,...]

Description

Alias for the lc command. Counts lines in files matching patterns. See 'man lc' for complete documentation.

Examples

    linecount /s *.cpp,*.h
        Count all C++ source files recursively.

    linecount /q *.py
        Quietly count Python files (total only).

See also

lc

local back to top ↑

declare a variable in the current procedure's scope

Synopsis

    local <name> [= <value>]
    local <name1> <name2> ... <nameN>

Description

Declares one or more variable names as local to the current proc. The variable disappears when the proc returns, restoring any global of the same name that was previously visible.

Without an `= value`, the variable is declared but left empty (and unset when the proc returns).

`local` outside a proc is a no-op for scoping purposes but still performs any assignment.

Options

    <name>      Variable name. Multiple names can be declared in one
                `local` statement.
    <value>     Optional initial value (only when one name is given).

Examples

    proc square
        local result
        @ result = $1 * $1
        echo $result
    endproc
    set result = "global-result"
    square 5            # prints 25
    echo $result        # still "global-result" -- local didn't leak

    proc tmp
        local a b c
        set a = 1
        set b = 2
        set c = 3
        echo $a $b $c
    endproc

Exit status

0       Always.

Notes

By default, `set` inside a proc already creates a local variable. The explicit `local` is mainly useful for: - Documenting intent ("these names are scoped to this proc") - Declaring multiple locals at once - Reserving a name BEFORE any conditional assignment to it, so later `set name = ...` doesn't accidentally hit a global of the same name when the conditional path skips the first write.

The counterparts that REACH OUT of local scope are `share` (writes through to the global namespace from a coroutine or proc) and the explicit global-variable accessors.

See also

set, unset, share, declare, readonly

log back to top ↑

tee stdout and stderr to a file while still showing them

Synopsis

    log FILE
    log -a FILE
    log off
    log

Description

Starts copying everything the shell produces -- standard output AND standard error, from builtins and from external programs alike -- into FILE, while you go on seeing it on screen.

This is not the same as `> file`, and the difference is the reason the command exists. A redirect captures ONE stream. Run something that reports problems on stderr and redirect only stdout, and the file fills with the successes while the terminal fills with the complaints -- the two halves of the story land in different places, and the half you are looking at is the alarming one.

`>&` captures both, but it is csh-specific spelling and it is the thing nobody remembers at the moment they need it. `log` is meant to be reachable without thinking: turn it on, do the thing that misbehaves, turn it off, attach the file.

Options

    FILE            Start logging to FILE, replacing anything already in it.

    -a, --append    Append instead of replacing. Useful across several runs
                    of the same reproduction.

    off             Stop logging, flush and close the file.

    (none)          Report whether logging is on and where it is going.
                    Exit status is 0 when logging, 1 when not, so
                    `log && echo capturing` works.

Notes

What is captured: - everything the shell itself prints, including error messages - everything a builtin prints on either stream - everything an external program prints on either stream, because the child inherits the same destination

What is NOT captured, deliberately: - the prompt, and the characters you type. Those are terminal echo, not output; a log full of half-typed lines and cursor movement is harder to read than one without them. - anything a command redirected somewhere else. `cmd > out.txt` still writes to out.txt and not to the log, exactly as it would without logging.

The file is flushed after every write, so it survives the shell hanging or being killed -- which is the case people usually turn logging on for.

Logging to a second file while the first is active is refused rather than silently switched. Two destinations in one session is much more likely to be a mistake than an intention.

Examples

    log session.txt
        Start capturing.

    log session.txt
    source run_all_tests.cshw
    log off
        Capture a whole test run -- passes and diagnostics together, in one
        file, in the order they happened.

    log -a repro.txt
        Add this run to a file that already holds an earlier one.

    log
        "logging to session.txt", or "not logging".

    cshw -log session.txt myscript.cshw
        The same from the command line, covering the startup files too --
        which a `log` command inside the script cannot reach.

See also

bugreport, tee, script

Exit status

0       Started, stopped, or logging is on
1       Not logging (for a bare `log`), or the file could not be opened

login back to top ↑

log in as a different user

Synopsis

    login [USERNAME]

Description

Initiates a login session as the specified user. This command is primarily for compatibility with UNIX shells. On Windows, actual user switching requires different mechanisms.

Options

    USERNAME        User to log in as.

Examples

    login
        Prompt for username and password.

    login administrator
        Log in as administrator.

Exit status

0       Success
1       Authentication failed
2       User not found

Notes

Windows Limitations: On Windows, true user switching within a console session has limitations. For full user switching, use: - Windows logoff/logon - runas command - Fast User Switching

runas Alternative: For running commands as another user: runas /user:DOMAIN\username command

Security: Credentials entered at the login prompt should be handled securely. Be cautious on shared or untrusted systems.

See also

logout, sudo, whoami

logout back to top ↑

end a login shell

Synopsis

    logout

Description

Ends a LOGIN shell -- the session's first shell, started with -l or --login. In any other shell this is an error:

Not login shell.

and the shell keeps running, at status 1. That is tcsh's behaviour, and it is what makes this something other than a synonym for `exit`: ending a login shell also runs ~/.logout, and ending a subshell must not.

Use `exit` for any shell. Use `logout` when you specifically mean "end this session", and want to be told if you are somewhere else.

Examples

    logout
        End the session, running ~/.logout on the way out.

    cshw -l
        Start a login shell, where logout is meaningful.

Exit status

Does not return in a login shell -- the shell exits, keeping whatever
status was in effect. A ~/.logout that runs commands does not change
it.
1       Not a login shell. Nothing happened.

Notes

What makes a login shell here: cshw is a login shell when it was started with -l or --login. It is DECLARED, not detected: tcsh knows because /bin/login execs it with an argv[0] of "-tcsh", and nothing on Windows does that, so there is no signal to read. The Start-menu shortcut passes -l; a cshw started from inside another cshw does not, which is exactly the distinction .login and .logout exist to make.

`if ($?loginsh) then ... endif` is how a script asks.

Running jobs: If background jobs are running you may be warned. Use `jobs` to see them, then decide whether to wait or exit anyway.

See also

exit, login, jobs, source

lp back to top ↑

send a file to a printer, or render it to a file

Synopsis

    lp [-d PRINTER] [MODE] [FILE...]
    lp --pdf FILE   [OPTIONS] [FILE...]
    lp --xps FILE   [OPTIONS] [FILE...]
    lp --image FILE [OPTIONS] [FILE...]

Description

Sends FILE to a printer. With no FILE, reads standard input, so lp sits at the end of a pipeline the way it does everywhere else:

fmt -w 65 letter.txt | pr -h "Draft" | lp

lp is the System V spelling and lpr is the BSD one. They are the same command here, and both accept -d and -P for the destination, so a script ported from either world runs unchanged.

With no printer named, the system default is used. `lpstat -d` shows it.

Options

    -d NAME, -P NAME    Printer to use. Default: the system default.
    -n N, --copies N    Number of copies.
    -T TEXT, --title    Job name, and the page title under --gdi.

  Mode -- how the bytes reach the page:

    (default)           RAW. The file is sent untouched.
    --raw               Same, said explicitly.
    --text              The spooler renders plain text (datatype TEXT).
    --gdi               cshw renders, using the layout options below.

  Layout, for --gdi and --image:

    --font NAME         Default Consolas.
    --size POINTS       Default 10.
    --margin INCHES     Default 0.5.
    --landscape         Rotate the page.

  Output to a file instead of a printer:

    --pdf FILE          Through Microsoft Print to PDF.
    --xps FILE          Through Microsoft XPS Document Writer.
    --image FILE        Rendered by cshw. No printer involved.
      --imagetype T     tiff | png | jpg | bmp. Default tiff.
      --dpi N           Default 200.
      --tiff-compression C    g4 | lzw | none. Default g4.

Examples

    lp report.ps
        RAW: the bytes go straight to the printer. Right when the file is
        already PostScript or PCL.

    lp --text notes.txt
        Let the spooler render the text.

    lp --gdi --font "Courier New" --size 9 --margin 1.0 notes.txt
        Render it here, with control over the layout.

    lp --pdf out.pdf notes.txt
    lp --xps out.xps notes.txt
        To a file, with no Save-As dialog.

    lp --image scan.tif --dpi 300 notes.txt
        A multi-page TIFF at 300 dpi.

    fmt -w 65 letter.txt | pr -h "Draft" | lp --pdf draft.pdf
        Reflow, paginate, render.

Exit status

0       The job was submitted, or the file was written
1       Failure -- the message says which

Notes

Choosing a mode -- and why lp will not choose for you: RAW is the default because it is the only mode that does not touch your data, and a caller sending PostScript wants exactly that. It is also the mode that fails most confusingly: a printer accepts RAW quite happily and then prints pages of garbage, because acceptance happens in the SPOOLER and interpretation happens in the DEVICE.

No Win32 API answers "does this device understand PostScript?", so lp does not guess. `lpstat -l` reports what it found -- driver, port, print processor, default datatype and the datatypes the processor accepts -- and you choose. A wrong guess here would waste a ream of paper quietly.

When a datatype is refused: The print processor's list is necessary but not sufficient: the DRIVER can refuse a datatype the processor advertises. On a stock Windows 11 machine winprint offers TEXT for every printer, yet Print to PDF, the XPS writer and OneNote all reject it with error 1804, while Fax accepts it. lp says so and names the way out rather than printing a bare number.

Multi-page image output: TIFF holds every page in one file. PNG, JPG and BMP cannot -- they are single-image formats -- so those write ONE FILE PER PAGE:

lp --image report.png --imagetype png    ->  report-pg1.png
                                             report-pg2.png
                                             report-pg3.png

Numbers are zero-padded to the width of the highest page, so a twelve-page document gives report-pg01.png .. report-pg12.png and the names still sort correctly. Every page is suffixed, including page 1 of a one-page document, so the name never depends on how long the document happens to be. lp prints each file it wrote.

Image size: A letter page of text, measured. TIFF-G4 is bilevel and dramatically smaller; JPEG is a poor fit for text, being both larger and lossy on the sharp edges text is made of.

DPI    TIFF-G4      PNG        JPG        BMP
 96      12 KB     58 KB     153 KB     3.4 MB
200      34 KB    344 KB     964 KB      15 MB
300      50 KB    435 KB     1.4 MB      34 MB

See also

lpr, lpq, lpstat, lprm, cancel, lpc, pr, fmt, fold

lpc back to top ↑

control a print queue

Synopsis

    lpc status [-P PRINTER]
    lpc stop   [-P PRINTER]
    lpc start  [-P PRINTER]
    lpc purge  [-P PRINTER]

Description

Inspects and controls a printer's queue: whether it is accepting work, and what to do about the jobs already in it.

Options

    status      Report whether queuing is enabled, and how many entries.
    stop        Pause the queue. Jobs accumulate; nothing prints.
    start       Resume it.
    purge       Discard every job in the queue.

    -P NAME, -d NAME    Printer. Default: the system default.

Examples

    lpc status
        Microsoft Print to PDF:
            queuing is enabled
            0 entries

    lpc stop -P "Front Desk"
        Hold everything while the paper is changed.

    lpc start -P "Front Desk"

    lpc purge -P "Front Desk"
        Throw away what is queued.

Exit status

0       The action succeeded
1       It did not -- the message says why

Notes

stop, start and purge change state shared with every other user of that printer, so they need the rights to manage it and fail with error 5 (access denied) without them. lpc says so explicitly and names sudo rather than failing obscurely. cshw never elevates itself.

purge is not undoable. lpq first if you want to know what you are about to discard.

See also

lpq, lprm, cancel, lp, lpr, lpstat

lpq back to top ↑

list the jobs in a print queue

Synopsis

    lpq [-P PRINTER]

Description

Shows what is waiting in a printer's queue: job id, owner, status, size and document name. With no printer named, the system default is used.

The job id is what lprm and cancel take.

Options

    -P NAME, -d NAME    Printer to inspect. Default: the system default.

Examples

    lpq
        Job    Owner            Status        Size  Document
        17     tarie            spooling     20480  report.txt

    lpq -P "Microsoft Print to PDF"

    lprm `lpq | awk 'NR>1 {print $1}'`
        Remove every job the queue is showing.

Exit status

0       The queue was read (including when it is empty)
1       The printer could not be opened

Notes

Status values come from the spooler: queued, spooling, printing, paused, printed, deleting, error. A job can sit in "spooling" for some time on a slow link; that is the spooler's business, not the printer's.

See also

lp, lpr, lpstat, lprm, cancel, lpc

lpr back to top ↑

send a file to a printer (BSD spelling of lp)

Synopsis

    lpr [-P PRINTER] [MODE] [FILE...]

Description

The BSD name for lp. They are the SAME command in cshw, with the same options and the same behaviour -- both accept -P and -d for the destination so a script written against either tradition runs unchanged.

Historically lpr (BSD) and lp (System V) were separate programs with gratuitously different flags. There is no reason to reproduce that here.

See lp(1) for the full description: the three modes (RAW, --text, --gdi), the file targets (--pdf, --xps, --image), layout options and image formats.

Options

    -P NAME, -d NAME    Printer to use
    -n N, --copies N    Number of copies
    -T TEXT, --title    Job name

See lp(1) for --raw, --text, --gdi, --pdf, --xps, --image, --imagetype,
--dpi, --tiff-compression, --font, --size, --margin and --landscape.

Examples

    lpr report.ps
    lpr -P "Front Desk" --text notes.txt
    cat notes.txt | lpr --gdi

Exit status

0       The job was submitted, or the file was written
1       Failure

See also

lp, lpq, lpstat, lprm, cancel, lpc

lprm back to top ↑

remove jobs from a print queue

Synopsis

    lprm [-P PRINTER] JOBID...
    lprm [-P PRINTER] -a

Description

Removes jobs from a printer's queue. Job ids come from lpq. With -a every job in the queue is removed.

`cancel` is the same command under its System V name.

Options

    -P NAME, -d NAME    Printer. Default: the system default.
    -a, --all           Remove every job in the queue.

Examples

    lpq
    lprm 17
        lprm: removed job 17 from Microsoft Print to PDF

    lprm -a
        Clear the whole queue.

    lprm -P "Front Desk" 12 13 14

Exit status

0       Every named job was removed
1       At least one could not be

Notes

Removing someone else's job needs the rights to manage the printer, and fails with error 5 (access denied) without them. cshw never elevates itself; run an elevated shell, or use sudo.

A job that has already finished printing is gone from the queue and cannot be removed -- lprm reports that rather than pretending it worked.

See also

cancel, lpq, lpc, lp, lpr

lpstat back to top ↑

show printers and what they will accept

Synopsis

    lpstat [-l] [-d]

Description

Lists the printers this machine knows about and marks the default. With -l it also reports the driver, port, print processor, default datatype, job count, and the datatypes the print processor will accept.

That last line is the point of the command. It is REPORTED so you can choose a mode for lp; it is never used to guess one.

Options

    -l, --long      Long form: driver, port, processor, datatype, jobs,
                    and accepted datatypes.
    -d, --default   Show only the system default destination.

Examples

    lpstat
        printer Microsoft XPS Document Writer  (default)
        printer Microsoft Print to PDF
        printer Fax

    lpstat -d
        system default destination: Microsoft XPS Document Writer

    lpstat -l
        printer Microsoft Print to PDF
            driver:   Microsoft Print To PDF
            port:     PORTPROMPT:
            processor:winprint
            datatype: RAW
            jobs:     0
            accepts:  RAW, RAW [FF appended], RAW [FF auto], NT EMF 1.003,
                      NT EMF 1.006, NT EMF 1.007, NT EMF 1.008, TEXT, XPS2GDI

Exit status

0       Always, including when there are no printers

Notes

Why this is a report and not a decision: There is no Win32 API that answers "does this device understand PostScript?" Two different things are being confused whenever someone tries to auto-detect:

* EnumPrintProcessorDatatypes says what the SPOOLER will accept. A
  printer takes RAW happily and then prints garbage, because acceptance
  happens in the spooler and interpretation happens in the device.
* The DRIVER can refuse a datatype the processor advertises. Measured on
  a stock Windows 11 box: winprint offers TEXT for every printer, yet
  Print to PDF, the XPS writer and OneNote all reject it with error 1804,
  while Fax accepts it.

So the 'accepts' line is necessary but not sufficient. Read it, then pick the mode yourself. lp will not guess, and when a datatype is refused it says which one and what to use instead.

See also

lp, lpr, lpq, lprm, cancel, lpc

ls back to top ↑

list directory contents (native, not a shell-out)

Synopsis

    ls [OPTION]... [FILE]...

Description

Lists files and subdirectories, following GNU coreutils' ls. Native implementation -- it does NOT shell out to an external ls.exe. With no FILE, lists the current directory.

Output goes to columns when it is heading for a console and to one name per line when it is redirected or piped, which is what GNU does and what makes `ls | wc -l` count files rather than screen rows.

Options

  What to list:

    -a, --all           Include entries starting with '.', and '.' and
                        '..' themselves. Also shows files Windows marks
                        hidden.
    -A, --almost-all    Like -a, but without '.' and '..'.
    -d, --directory     List the DIRECTORY ITSELF, not its contents.
                        `ls -ld folder` reports on the folder; `ls -d */`
                        lists directories without descending into them.
    -R, --recursive     Descend into subdirectories.

  How to show it:

    -l                  Long format: mode, links, owner, group, size,
                        time, name.
    -1                  One entry per line.
    -C                  Multi-column, filling down each column.
    -x                  Multi-column, filling across each row.
    -m                  Comma-separated, filled to the terminal width.
    -F, --classify      Append an indicator: / directory, * executable,
                        @ reparse point.
    -p                  Append / to directories only.
    -Q, --quote-name    Enclose each name in double quotes.
    -i, --inode         Show the file index -- Windows' nearest thing to
                        an inode. Costs a handle open per entry, so it is
                        only fetched when asked for.
    -s, --size          Show the size in 1K blocks.
    -h, --human-readable  Sizes as 1K, 234M, 2G.
    --si                The same, in powers of 1000.
    -g                  Like -l, but omit the owner.
    -o, -G, --no-group  Like -l, but omit the group.
    -n, --numeric-uid-gid  Like -l with numeric ids.
    --full-time         Long format with a full ISO timestamp.
    --time-style=STYLE  long-iso / iso / full-iso select the ISO layout.

  Sorting:

    (default)           By name, case-insensitively.
    -t                  By time, newest first.
    -S                  By size, largest first.
    -X                  By extension.
    -v                  Natural order, so file10 follows file9 rather
                        than file1.
    -U, -f              Unsorted -- directory order, which is fastest.
    -r, --reverse       Reverse whatever order is in effect.
    -c                  Use the creation time (with -l or -t).
    -u                  Use the access time (with -l or -t).
    --group-directories-first
                        Directories before files.

Examples

    ls
        The current directory, in columns.

    ls -l
        Long form.

    ls -lh
        ...with sizes a person can read.

    ls -lt
        Newest first -- what changed while you were away.

    ls -ld C:\Projects
        About the FOLDER: its own mode, owner and date.

    ls -lR src
        Long, recursive.

    ls -1 | wc -l
        Count entries. Redirected output is one per line anyway, so the
        -1 is only there to say so.

    ls *.cshw
        A pattern. The shell normally expands this before ls sees it; a
        QUOTED pattern is expanded by ls itself.

Exit status

0       Everything named was listed
1       Something could not be accessed
2       An unrecognized option

Notes

Reading `ls -l`:

-rw-r--r-- 1 tarie tarie 4321 Aug  1 21:24 notes.txt
drwxr-xr-x 1 tarie tarie    0 Aug  1 21:24 Projects

The first character is the type: '-' a file, 'd' a directory, 'l' a reparse point. The nine that follow are permission bits, synthesized from what Windows actually records -- NTFS has no owner/group/other triad, so the group and other columns mirror the owner's read and execute bits. A read-only file loses its 'w'; anything Windows would execute gains an 'x'. This is the same presentation msys and WSL give an NTFS file.

The timestamp follows GNU: "Mon DD HH:MM" for something within the last six months, "Mon DD YYYY" for anything older -- a year being more use than a clock time once a file is old. --full-time gives the exact ISO form.

Deliberate differences from GNU: * The group column repeats the owner. Windows has no numeric GID, and the security descriptor's primary group is almost never what a reader means by "group". * The link count is always 1. Counting hard links means opening every file, and the cost is not worth a column almost nobody reads. * A QUOTED wildcard is expanded by ls rather than refused. GNU leaves globbing entirely to the shell and errors on a pattern; cshw's ls has always expanded one, and scripts rely on it. * --color is accepted and ignored.

Every other option is either implemented or refused. An unrecognized flag is an ERROR, not a silent no-op -- `ls --colour=auto`, or any typo, used to be accepted and quietly change nothing.

See also

dir, tree, find, glob, stat, du

man back to top ↑

display manual pages

Synopsis

    man [command]
    man -k keyword

Description

Displays comprehensive documentation for CSHW shell commands. Man pages provide detailed information including syntax, options, examples, and related commands.

Without arguments, lists all available manual pages.

Options

    command         Display the manual page for this command.

    -k keyword      Search manual pages for keyword in names and
                    descriptions.

Examples

    man
        List all available manual pages.

    man grep
        Display manual page for grep command.

    man cd
        Display manual page for cd command.

    man -k file
        Find commands related to "file".

    man -k network
        Find network-related commands.

Exit status

0       Success
1       Manual page not found

Notes

Bracket pages: `man [` and `man ]` both show test.man, which documents the pair. The operand has to be recovered from the raw command line: a bare `[` or `]` is stripped before a builtin sees it -- the same handling that lets `[ 1 -eq 1 ]` work -- so `man [` used to run with no arguments at all and list every page in the manual.

Keyword search: `man -k WORD` searches every page's name, summary and description. `-k` alone is a usage error, not a request for the full listing.

Man Page Format: Manual pages are organized into sections: NAME - Command name and brief description SYNOPSIS - Usage syntax DESCRIPTION - Detailed explanation OPTIONS - Available options and switches EXAMPLES - Usage examples EXIT_STATUS - Return codes NOTES - Additional information SEE_ALSO - Related commands

Man Page Location: Manual pages are stored as .man files. The shell searches for them in this order: 1. Directory specified by CSHW_MAN environment variable 2. 'man' subdirectory alongside the shell executable

Comparison with Help: - 'help' provides brief usage information - 'man' provides comprehensive documentation

Creating Man Pages: Man pages use a simple text format with section headers starting with a period (.NAME, .SYNOPSIS, etc.).

Environment

CSHW_MAN        Directory containing .man files. If set and the
                directory exists, man pages are loaded from here
                instead of the default location.

See also

help

md back to top ↑

make a directory (alias for mkdir)

Synopsis

    md <directory>

Description

`md` is identical to `mkdir`. See `man mkdir` for full documentation.

See also

mkdir, rd, rmdir

md5sum back to top ↑

compute MD5 message digest

Synopsis

    md5sum FILE...
    command | md5sum

Description

Computes and displays the MD5 hash (128-bit) of files. MD5 produces a 32-character hexadecimal fingerprint that changes if the file changes.

Options

    FILE            One or more files to hash.

    -c FILE         Check MD5 sums against a checksum file.

Examples

    md5sum file.txt
        Compute MD5 hash of file.txt.

    md5sum *.iso
        Hash all ISO files.

    md5sum -c checksums.md5
        Verify files against saved checksums.

    type data.bin | md5sum
        Hash piped input.

    md5sum file.zip > file.zip.md5
        Save checksum to file.

Exit status

0       Success (or all checksums verified)
1       Checksum mismatch (verify mode)
2       File not found

Notes

Piped input: With no file operand and a redirected stdin, md5sum hashes what it is given and prints "-" in the filename column, the way GNU does. The stream is treated as text and hashed as UTF-8, so the digest matches what GNU produces for the same text. An interactive shell with nothing piped in gets the usage message rather than blocking on the terminal.

Output Format: d41d8cd98f00b204e9800998ecf8427e filename.txt

Security Warning: MD5 is cryptographically broken and should NOT be used for security purposes. Use SHA-256 or SHA-512 for security applications. MD5 is still acceptable for: - Non-security integrity checks - Duplicate file detection - Cache keys

Verification: Create checksum files for later verification: md5sum *.zip > checksums.md5 # Later... md5sum -c checksums.md5

See also

sha256sum, sha512sum, sha1sum

messagebox back to top ↑

show a Win32 message box

Synopsis

    messagebox <message> [<title>] [<type>]
    msgbox     <message> [<title>] [<type>]
    messagebox <message> [<title>] [/type:<flags>]

Description

Wraps the Win32 MessageBoxW API. Shows a modal message with one of the standard button sets and icons, waits for the user, and reports which button was pressed.

`messagebox` and `msgbox` are two names for one command.

MESSAGE COMES FIRST. The title is optional and defaults to "cshw". Earlier versions of this command took its arguments the other way round -- caption first, title mandatory -- which matched neither this page nor Win32's own MessageBox(hwnd, text, caption, type).

THE BUTTON LANDS IN $status AND $result. Both hold the Win32 ID constant, so a script can branch on either without capturing output. Nothing is printed to stdout; the dialog is the output.

msgbox "Continue?" "Confirm" yesno,question
if ($result == 6) then
    echo "user said yes"
endif

Because the exit status carries the button rather than success or failure, `msgbox ... || cmd` fires for anything except OK (1). Test $result, or compare against the specific button you mean.

Options

    <message>       The body of the message. Required.
    <title>         Window caption. Default: "cshw".
    <type>          A number, or a comma-separated list of names. Names
                    and numbers may be mixed; values combine the same
                    way the MB_* constants do.

                    Buttons:  ok(0) okcancel(1) abortretryignore(2)
                              yesnocancel(3) yesno(4) retrycancel(5)
                    Icons:    error/stop(16) question(32)
                              warning/exclamation(48) info(64)
                    Other:    defbutton1 defbutton2 defbutton3
                              systemmodal taskmodal topmost

                    MB_ prefixes are accepted: MB_YESNO reads the same
                    as yesno.

    /type:<flags>   The same list as a switch, for the spelling this
                    page has always documented. Combines with a
                    positional type rather than replacing it.

    An unknown type name is refused before any dialog appears, so a typo
    is reported rather than silently producing a plain OK box.

Examples

    messagebox "Hello, world"
        Simple message box titled "cshw".

    msgbox "Operation complete" "Status"
        Custom title.

    msgbox "Continue?" "Confirm" yesno,question
        Yes/No prompt with a question icon.

    msgbox "Are you sure?" "Confirm" 36
        The same thing numerically: 4 (yesno) + 32 (question).

    msgbox "File not found" "Error" error
        Error icon, OK button.

    msgbox "Are you sure?" "Warning" yesnocancel,warning
        if ($result == 6) echo "Yes"
        if ($result == 7) echo "No"
        if ($result == 2) echo "Cancel"

    messagebox "Continue?" "Confirm" /type:yesno,question
        Switch spelling, same result.

Exit status

The button pressed, as the Win32 ID:
1       OK
2       Cancel
3       Abort
4       Retry
5       Ignore
6       Yes
7       No
A usage error (no message, too many operands, unknown type name)
reports the problem and returns without showing a dialog.

Notes

Blocking: The shell waits for the user to click a button. A script running unattended stops here until someone answers.

$result and $status: $result is the one to prefer -- it is not overwritten by the next command's success or failure the way $status is.

GUI Interaction: Message boxes appear in the foreground and take focus. Add topmost if the dialog must sit above other windows.

See also

msgbox, passworddlg, about

mkdir back to top ↑

create directories

Synopsis

    mkdir DIRECTORY
    mkdir -p DIRECTORY
    md DIRECTORY

Description

Aliases: md

Creates one or more directories. Can create nested directory structures in a single command with the -p option.

Options

    DIRECTORY       The directory path to create.

    -p, --parents   Create parent directories as needed. No error if
                    the directory already exists.

Examples

    mkdir newdir
        Create directory 'newdir' in current location.

    mkdir C:\Users\Me\Projects\NewProject
        Create directory with absolute path.

    mkdir -p deep/nested/directory/structure
        Create entire directory tree.

    mkdir "My Documents"
        Create directory with spaces in name.

    md backup
        Create 'backup' directory (md is alias for mkdir).

Exit status

0       Success
1       Parent directory doesn't exist (without -p)
2       Access denied
3       Directory already exists (without -p)

Notes

Parent Directories: Without -p, all parent directories must already exist. With -p, missing parents are created automatically.

Permissions: New directories inherit permissions from the parent directory on Windows.

Network Paths: UNC paths (\\server\share\dir) are supported.

See also

rmdir, cd, dir

more back to top ↑

display text one screen at a time

Synopsis

    more [/s] [FILE]...
    command | more

Description

Shows text a screenful at a time, pausing between screens. With no FILE, reads standard input. Several files are shown in turn, each introduced by a *** name *** banner.

The screen size comes from the console, so the page grows and shrinks with the window.

Options

    /s          Squeeze runs of blank lines down to one.

Controls

At the -- More -- prompt:

    Enter       Show one more LINE
    q, Esc      Stop
    any key     Show the next SCREEN

Examples

    more notes.txt
        Page one file.

    dir /s | more
        Page a long listing.

    more /s report.txt
        Page it with the blank runs collapsed.

Exit status

0       The text was displayed
1       One or more files could not be opened

Notes

When the output is NOT a console -- redirected to a file, or piped onward -- more passes the text through unpaged and never prompts.

That is what makes it safe to leave in a script. A pager that paused for a keypress in a pipeline would wait for a key that is never coming WHILE HOLDING THE PIPE, so the reader on the other end would wait too, and the script would hang with no output and no explanation.

See also

cat, type, head, tail, pr, fold

msgbox back to top ↑

display a message box

Synopsis

    msgbox MESSAGE
    msgbox MESSAGE TITLE
    msgbox MESSAGE TITLE TYPE

Description

Displays a Windows message box with the specified message, an optional title, and an optional button/icon configuration. The command waits for the user and reports the button clicked.

`msgbox` and `messagebox` are two names for one command; see `man messagebox` for the full reference. The essentials:

MESSAGE COMES FIRST, the title defaults to "cshw", and the button pressed lands in BOTH $status and $result as the Win32 ID. Nothing is printed to stdout.

Options

    MESSAGE         The message text to display.
    TITLE           Window title (default: "cshw").
    TYPE            Button and icon configuration, numeric or named.
                    Names may be combined with commas.

    Type values:
    0, ok           OK button only
    1, okcancel     OK and Cancel buttons
    2, abortretryignore
                    Abort, Retry, Ignore buttons
    3, yesnocancel  Yes, No, Cancel buttons
    4, yesno        Yes and No buttons
    5, retrycancel  Retry and Cancel buttons

    Add for icons:
    16, error       Error icon (X)
    32, question    Question mark icon (?)
    48, warning     Warning icon (!)
    64, info        Information icon (i)

    Also accepted: defbutton1, defbutton2, defbutton3, systemmodal,
    taskmodal, topmost, and MB_-prefixed spellings.

Examples

    msgbox "Hello World"
        Simple message with OK button.

    msgbox "Operation complete" "Status"
        Message with custom title.

    msgbox "Delete this file?" "Confirm" yesno
        Yes/No confirmation dialog.

    msgbox "File not found" "Error" 16
        Error message with error icon.

    msgbox "Are you sure?" "Confirm" 36
        Yes/No (4) + Question icon (32).

    msgbox "Are you sure?" "Confirm" yesno,question
        The same thing, spelled out.

Exit status

Returns the button clicked:
1       OK
2       Cancel
3       Abort
4       Retry
5       Ignore
6       Yes
7       No

Notes

Blocking: The shell waits for the user to click a button before continuing. This pauses script execution.

Return value: $result and $status both hold the button. Prefer $result -- $status is overwritten by the next command, and because it carries a button rather than success or failure, `msgbox ... || cmd` fires for every answer except OK:

msgbox "Continue?" "Confirm" yesno
if ($result == 6) then
    echo "User clicked Yes"
endif

GUI Interaction: Message boxes appear in the foreground and grab focus. They work even when the shell is running in the background.

Scripting: Useful for user confirmations, error notifications, and interactive scripts that need user decisions. A script running unattended will stop at a msgbox until someone answers it.

See also

messagebox, passworddlg, echo, read

mutex back to top ↑

mutual-exclusion lock

Synopsis

    mutex <name> create
    mutex <name> lock
    mutex <name> trylock [/timeout:ms]
    mutex <name> unlock
    mutex <name> status
    mutex <name> destroy

Description

A named mutual-exclusion lock, shared across coroutines and worker threads by name. You must create it before use; lock/unlock/trylock/status on an unknown name is an error (this catches typos instead of quietly auto-creating). unlock is owner-checked -- unlocking a mutex you do not hold is a reported error, not undefined behavior. Names live in the process-wide sync table; list them with `sync list mutex` and remove them with destroy or `sync destroy`.

Options

    create              Create the mutex (idempotent).
    lock                Acquire, blocking until it is available.
                        FATAL ON FAILURE -- see below.
    trylock [/timeout:ms]
                        Try to acquire; $? = 0 acquired, 1 busy. With
                        /timeout:ms, wait up to that long before giving up.
                        Never fatal: this is the verb for "tell me whether
                        I can have it".
    unlock              Release; error if not held by this thread.
    status              Show locked/unlocked and the owner thread id.
    destroy             Remove the mutex.

.WHY LOCK IS FATAL
A failed acquire followed by the critical section is data corruption, and it is
not the script's judgement call to make -- you cannot be past an acquire without
holding the lock. `mutex lock` used to report the failure, set $status, and fall
through to the very code it had failed to protect:

    mutex counter_lock lock          <- failed, printed an error
    ...critical section...           <- ran anyway, unprotected

so a misspelled lock name gave every coroutine free rein over the shared state
with no symptom other than wrong answers. `lock` now stops the script (or the
coroutine, leaving the others and the shell alone). Nothing is lost: `trylock`
already existed for the case where not getting the lock is an outcome you mean
to handle, and it now carries /timeout: so a bounded wait is still available.

Examples

    mutex m create
    mutex m lock
    # ... critical section ...
    mutex m unlock

Exit status

0       Operation succeeded (trylock: acquired).
>0      Lock timeout, unlock not-owned, unknown name, or bad usage.

See also

semaphore, event, barrier, channel, sync, corunproc

mv back to top ↑

move or rename files and directories

Synopsis

    mv [OPTION]... SOURCE DEST
    mv [OPTION]... SOURCE... DIRECTORY
    mv [OPTION]... -t DIRECTORY SOURCE...

Description

Aliases: rename, move

Moves SOURCE to DEST, or moves several SOURCEs into DIRECTORY. Moving and renaming are the same operation: a rename is a move whose destination happens to be in the same directory.

On one volume a move only rewrites a directory entry, so even a very large file moves instantly. Across volumes the data has to be copied and the original removed, which mv does for you unless --no-copy says not to.

Options

  Overwrite policy:

    -f, --force, /y     Overwrite without asking. This is the default.
    -i, --interactive   Ask before overwriting an existing destination.
    -n, --no-clobber    Never overwrite; leave the destination alone.

    If more than one of these is given, THE LAST ONE WINS -- which is
    how GNU mv resolves it, so an alias carrying -i can still be
    overridden by a trailing -f on the command line.

  Backups:

    -b                  Back up an existing destination before it is
                        overwritten. Simple backup, unless
                        VERSION_CONTROL says otherwise.
    --backup[=CONTROL]  Back up, choosing the scheme:
                            none, off        no backups
                            numbered, t      file.~1~, file.~2~, ...
                            existing, nil    numbered if numbered
                                             backups already exist,
                                             otherwise simple
                            simple, never    one backup, file~
    -S, --suffix=SUF    Suffix for a simple backup. Default "~", or
                        SIMPLE_BACKUP_SUFFIX from the environment.

  Targets:

    -t, --target-directory=DIR
                        Move every SOURCE into DIR. Useful when the
                        sources come from a glob, which would otherwise
                        have to leave the directory last.
    -T, --no-target-directory
                        Treat DEST as an ordinary file even if a
                        directory of that name exists. Exactly one
                        SOURCE is allowed.
    --strip-trailing-slashes
                        Drop trailing slashes from each SOURCE.

  Other:

    -u, --update        Move only when SOURCE is newer than the
                        destination, or the destination is missing.
    -v, --verbose       Say what was moved, skipped, or backed up.

  Windows move modes:

    --write-through     Do not return until the move is on the disk.
    --no-copy           Refuse a cross-volume move rather than falling
                        back to copy-and-delete.
    --delay, --delay-until-reboot
                        Schedule the move for the next boot. This is how
                        a file something else has open gets replaced. It
                        is recorded in the registry, needs administrator
                        rights, and cannot copy across volumes.
    --hardlink          Move by creating a second name for the same data
                        and removing the first. Same volume only.
    --fail-if-not-trackable
                        Fail rather than move a file the link-tracking
                        service cannot follow.

Examples

    mv old.txt new.txt
        Rename.

    mv file.txt Documents\
        Move a file into an existing directory.

    mv project\ archived\project\
        Move a whole directory. A trailing slash on a destination that
        does NOT exist names the destination itself, so this renames
        project to archived\project rather than trying to create
        archived\project\project.

    mv "My File.doc" "Renamed File.doc"
        Names with spaces need quoting, as everywhere else.

    mv *.log archive/
        Move many files into a directory.

    mv -t archive/ *.log
        The same, with the directory named first.

    mv -i important.conf C:\etc\
        Ask before clobbering.

    mv -b -S .orig config.ini C:\srv\config.ini
        Keep the old destination as C:\srv\config.ini.orig.

    mv --backup=numbered report.pdf C:\reports\
        Keep every previous version: report.pdf.~1~, ~2~, ...

    mv -u -v build\*.dll dist\
        Refresh only what changed, and say what moved.

    mv --delay locked.dll "C:\Program Files\App\locked.dll"
        Replace a DLL that is currently loaded; it lands on next boot.

Exit status

0       Every requested move was performed, or correctly skipped
1       At least one move failed
A move that -n or -u declined to perform is the requested outcome,
not a failure, and does not set a non-zero status.

Notes

Every one of the overwrite flags used to be inert.

mv passed MOVEFILE_REPLACE_EXISTING unconditionally and read no switches at all, so -i never asked and -n overwrote the very file it exists to protect -- while reporting success. Both were documented here and recommended in the book. A script relying on the old behaviour was relying on mv ignoring what it was told.

MOVEFILE_CREATE_HARDLINK is reserved by Windows and does nothing at all, so --hardlink is implemented directly with CreateHardLink plus removal of the source name, which is what the flag was always meant to mean.

Cross-drive moves copy and then delete, so they are slower than a move within one volume and are not atomic.

See also

cp, rm, ren, move, copy, del, ls, dir

nice back to top ↑

run command with modified priority

Synopsis

    nice COMMAND [ARGS...]
    nice -n ADJUSTMENT COMMAND

Description

Runs a command with adjusted scheduling priority. Lower priority allows other processes to get more CPU time, useful for background tasks.

Options

    COMMAND         Command to run.
    -n ADJUSTMENT   Priority adjustment (-20 to 19, default: 10).
                    Positive = lower priority (nicer)
                    Negative = higher priority (requires admin)

    Windows priority mapping:
    -20 to -10      High priority
    -9 to 0         Above normal
    1 to 9          Normal
    10 to 14        Below normal
    15 to 19        Idle/Low priority

Examples

    nice compress.exe largefile
        Run compression at lower priority.

    nice -n 15 backup.bat
        Run backup at very low priority.

    nice -n -5 important.exe
        Run at higher priority (needs admin).

    nice -n 19 longprocess.exe
        Run at lowest priority (idle).

Exit status

Returns the exit code of the command.

Notes

CPU Scheduling: Nice processes still run, just with lower priority. They get CPU time when higher-priority processes don't need it.

Negative Values: Increasing priority (negative nice) typically requires Administrator privileges on Windows.

Windows Priorities: Windows has fewer priority levels than UNIX. Nice values are mapped to the closest Windows priority class.

Background Tasks: Use nice for: - Backups - File compression - Large builds - Any task that shouldn't slow foreground work

Real-Time Priority: Extremely high priorities can make the system unresponsive. Use with caution.

See also

time, bg, jobs

nl back to top ↑

number the lines of a file

Synopsis

    nl [OPTIONS] [FILE...]

Description

Writes each line of FILE to standard output with a line number in front of it. With no FILE, or when FILE is absent, reads standard input, so nl is usable in the middle of a pipeline.

By default only NON-BLANK lines are numbered; blank lines are printed with the number column left empty. That is the behaviour scripts expect, and it is why `nl` and `cat -n` differ.

Options

    -b STYLE        Which body lines to number:
                      a   every line, blank ones included
                      t   non-blank lines only (the default)
                      n   no lines at all
    -w N            Width of the number field. Default 6.
    -s STR          Separator printed after the number. Default is a TAB.
    -v N            Number of the first line. Default 1.
    -i N            Increment between line numbers. Default 1.

Examples

    nl notes.txt
        #      1<TAB>first line
        #      2<TAB>second line

    nl -ba notes.txt
        Number blank lines too.

    nl -w3 -s': ' notes.txt
        #   1: first line

    nl -v100 -i10 notes.txt
        Start at 100 and count in tens.

    grep ERROR log.txt | nl
        Number the matches.

Exit status

0       Success
1       A named file could not be opened

Notes

Why this is a built-in: pr, fold, fmt and nl were the last commonly-scripted Unix text tools cshw did not provide. On a machine with Git for Windows installed they appeared to work, because Git ships its own nl.exe and puts it on PATH -- so a script using nl ran here and failed on a clean Windows box, and the test suite could not tell the difference. They are built in now, so behaviour no longer depends on what else happens to be installed.

See also

cat, fmt, fold, pr, wc

nohup back to top ↑

run command immune to hangups

Synopsis

    nohup COMMAND [ARGS...]

Description

Runs a command that will continue running even if the shell is closed or the user logs out. Output is redirected to nohup.out if not already redirected.

Options

    COMMAND         Command to run.
    ARGS            Arguments for the command.

Examples

    nohup longprocess.exe
        Run process that survives shell exit.

    nohup backup.bat &
        Background nohup process.

    nohup script.bat > output.log 2>&1 &
        Nohup with explicit output redirection.

    nohup server.exe &
        Start server that persists after logout.

Exit status

Returns immediately if backgrounded, otherwise returns command's
exit code.

Notes

Output: If stdout is a terminal, output redirects to nohup.out in the current directory (or $HOME/nohup.out if that fails).

Combination with &: nohup is typically combined with & to run in background: nohup command &

Signals: nohup makes the process ignore SIGHUP (hangup signal), which is sent when the terminal closes.

Use Cases: - Long-running server processes - Batch jobs that take hours - Processes that should survive logout

Windows Equivalent: On Windows, this is similar to starting a process detached from the console, allowing it to continue after shell exit.

Checking Status: Use 'processlist' or Task Manager to check if the process is still running.

See also

bg, jobs, start

nop back to top ↑

no operation (alias for true)

Synopsis

    nop

Description

Does nothing; succeeds with $status = 0. Aliased at the dispatcher to `true`. Documented alongside `true` and `false` on a single page -- see `man true` for full details.

See also

true, false

notify back to top ↑

enable job completion notifications

Synopsis

    notify
    notify %JOBID

Description

Enables or displays asynchronous notification when background jobs complete. When enabled, the shell immediately displays a message when a job finishes, rather than waiting until the next prompt.

Options

    (no args)       Show notification settings.
    %JOBID          Enable notification for specific job.

Examples

    notify %1
        Enable notification for job 1.

    longprocess &
    notify %1
        Start background job and enable notification.

    # When job completes:
    # [1]    Done                    longprocess

Exit status

0       Success
1       No such job

Notes

Default Behavior: By default, job completion is reported at the next prompt. With notify, you're informed immediately.

Use Cases: - Long-running background tasks - Multiple background jobs - When you need to know completion time precisely

Notification Format: [JOB#] Status Command Example: [1] Done backup.bat

Per-Job Setting: notify is set per job. Enable for jobs where you want immediate notification.

See also

jobs, bg, fg

onintr back to top ↑

set interrupt handler

Synopsis

    onintr
    onintr LABEL
    onintr -

Description

Specifies what happens when an interrupt signal (Ctrl+C) is received. Can ignore interrupts, handle them with a label, or restore default behavior.

Options

    (no args)       Restore default interrupt handling.
    LABEL           Jump to LABEL when interrupted.
    -               Ignore interrupts (disable Ctrl+C).

Examples

    onintr cleanup
        # ... code that might be interrupted ...
        exit 0
    cleanup:
        echo "Cleaning up..."
        rm -f temp_*
        exit 1
        # When Ctrl+C pressed, jumps to 'cleanup'

    onintr -
        # Critical section - ignore interrupts
        important_operation
    onintr
        # Restore normal interrupt handling

Exit status

0       Success

Notes

Use Cases: - Clean up temporary files on interrupt - Save state before exiting - Prevent interruption during critical operations

Label Handling: When interrupted, the shell jumps to the specified label and continues execution from there.

Nested Handlers: Save and restore handlers for nested operations: onintr outer_handler # ... code ... onintr inner_handler # ... critical code ... onintr outer_handler # ... more code ...

Critical Sections: Use 'onintr -' to prevent interruption during operations that must complete atomically.

See also

exit, trap

password back to top ↑

read a password from the console (no echo)

Synopsis

    password [/prompt:<text>] [/confirm]

Description

Reads a line of input from the console with echo suppressed and stores it in $result. The console-mode counterpart of `passworddlg`. Suitable for scripts that need a password and are running without a GUI (over SSH, in CI, etc.).

Options

    /prompt:<text>
        Prompt string. Default: "Password: ".
    /confirm
        Prompt twice and only return success if both entries match.

Examples

    password
        Read a password silently. $result holds the value.

    password /prompt:"SSH passphrase: "
        Custom prompt text.

    password /confirm
        Read twice, must match. Useful for setting a new password.

Exit status

0       Password read successfully.
1       User cancelled (Ctrl-C), or /confirm fields differ.

Notes

Echo is suppressed via the console mode flags; only newline / backspace appear visibly while the user is typing.

See also

passworddlg

passworddlg back to top ↑

prompt for a password using a modal dialog

Synopsis

    passworddlg [/title:<text>] [/prompt:<text>] [/confirm]

Description

Shows a modal password-entry dialog and stores the entered password in $result. With /confirm, presents a second edit field and only returns success when both fields match.

The dialog runs on the UI thread (with fallback to a calling-thread modal pump in non-interactive mode) and routes activation correctly so the first edit field gets focus on open.

Options

    /title:<text>
        Window title. Default: "Password".
    /prompt:<text>
        Prompt label above the edit field. Default: "Enter password:".
    /confirm
        Add a second edit field and require both entries to match.

Examples

    passworddlg
        Simple password prompt. $result has the password on OK.

    passworddlg /title:"Backup" /prompt:"Backup passphrase:"
        Custom title and prompt.

    passworddlg /confirm /prompt:"New password:"
        Two-field confirm form. Fails if the two fields don't match.

Exit status

0       User clicked OK; $result holds the password.
1       User cancelled, or /confirm fields didn't match.

Notes

$result is set even on cancel (to an empty string) -- check $status to distinguish OK from cancel rather than testing $result for empty.

The console-mode equivalent (no GUI) is the `password` command.

See also

password, about, splash

pathmap back to top ↑

map Unix-style paths to Windows destinations

Synopsis

    pathmap add <unix> <win> [<win> ...]
    pathmap del <unix>
    pathmap list
    pathmap clear

Description

Maps Unix-style path prefixes (`/tmp`, `/usr/local/bin`, `/home/$USER`) to Windows destinations. cshw consults this table for any path argument that starts with `/`, BEFORE its built-in WSL / Cygwin / MSYS translations. An entry may list several destinations; they are tried in order and the first existing one wins.

Destination strings may contain %ENV% and $VAR references; they resolve at lookup time, not when the entry is added -- so a table that references $HOME stays correct across user accounts.

Defaults ship in <install>/pathmap.csh. To override per-user, create %APPDATA%/cshw/pathmap.csh; when present, cshw sources it instead of the shipped defaults during startup.

Options

    add <unix> <win> [win ...]  Register a prefix mapping (multiple destinations
                                are tried in order; first-existing wins).
    del <unix>                  Remove the entry for <unix>.
    list                        Print all entries.
    clear                       Drop every entry.

Examples

    pathmap add /tmp %TEMP%
    pathmap add /home/$USER %USERPROFILE%
    pathmap list

Exit status

0       Subcommand succeeded.
>0      Bad usage / unknown subcommand.

See also

cd, settings, source

peinfo back to top ↑

display PE file information

Synopsis

    peinfo FILE
    peinfo [options] FILE

Description

Displays detailed information about Windows Portable Executable (PE) files, including EXE, DLL, SYS, and other PE formats. Shows headers, sections, imports, exports, and other metadata.

Options

    FILE            PE file to analyze.

    -h, --headers   Show PE headers only.
    -s, --sections  Show section information.
    -i, --imports   Show imported functions.
    -e, --exports   Show exported functions.
    -r, --resources Show resources.
    -a, --all       Show all information.

Examples

    peinfo program.exe
        Display basic PE information.

    peinfo -a C:\Windows\System32\kernel32.dll
        Full analysis of kernel32.

    peinfo -i malware.exe
        Show imports (useful for analysis).

    peinfo -e library.dll
        Show exported functions.

    peinfo -s driver.sys
        Show section layout.

Exit status

0       Success
1       File not found
2       Not a valid PE file

Notes

Information Displayed: - Machine type (x86, x64, ARM) - Subsystem (GUI, Console, Driver) - Entry point address - Section table (code, data, resources) - Import table (DLLs and functions used) - Export table (functions provided) - Timestamps, checksums

Security Analysis: peinfo is valuable for malware analysis: - Check imports for suspicious APIs - Examine section characteristics - Verify digital signatures - Detect packers/obfuscation

PE Format: The PE format is used by Windows executables, DLLs, drivers, and other binary files. Understanding PE structure helps with debugging and security analysis.

Packed Files: Packed/encrypted executables may show unusual characteristics: - Few imports - High entropy sections - Unusual section names

See also

file, strings, hexdump

popd back to top ↑

pop directory from stack and change to it

Synopsis

    popd

Description

Removes the top directory from the directory stack and changes to that directory. Used in conjunction with pushd to navigate back to previously saved locations.

Examples

    pushd C:\Projects
    # work in Projects...
    popd
        Return to the directory where pushd was issued.

    pushd dir1
    pushd dir2
    popd
        Return to dir1.
    popd
        Return to original directory.

Exit status

0       Success
1       Directory stack is empty
2       Cannot change to directory (deleted or inaccessible)

Notes

Empty Stack: If the directory stack is empty, popd will display an error message. Use 'dirs' to check the stack contents.

Deleted Directories: If the directory on the stack no longer exists (was deleted while you were elsewhere), popd will fail.

See also

pushd, dirs, cd

postmessage back to top ↑

post a Win32 message to a window's queue (async)

Synopsis

    postmessage <hwnd> <msg> [<wParam> [<lParam>]]

Description

Calls PostMessageW(hwnd, msg, wParam, lParam). The message is appended to the target window's thread message queue and the call returns immediately. $result is 1 on success, 0 on failure.

`msg` accepts the same symbolic-WM_* names and numeric forms as `sendmessage`.

Options

    <hwnd>      Target HWND in hex or decimal. Must satisfy IsWindow().
    <msg>       Symbolic (WM_CLOSE, ...) or numeric.
    <wParam>    WPARAM. Default 0.
    <lParam>    LPARAM. Default 0.

Examples

    # Fire-and-forget close request:
    postmessage $w WM_CLOSE

    # Post a custom WM_USER notification (plugins may translate this
    # into a script-event via DispatchScriptEvent):
    postmessage $w WM_USER 1 0

Exit status

0       PostMessage returned TRUE; $result = 1.
1       PostMessage returned FALSE; $result = 0. Use $? for the
        Windows error code.

Notes

Use `sendmessage` when the message handler needs to run BEFORE the script continues (e.g., the WM_CLOSE veto path). Use `postmessage` when you want the script to keep running without waiting.

See also

sendmessage, bindevent

pr back to top ↑

paginate text for printing

Synopsis

    pr [-t] [-n] [-h TEXT] [-l N] [FILE...]

Description

Arranges text into pages for printing: a header on each page carrying the date, a title and a page number, optional line numbers, and padding so each page is a fixed number of lines. With no FILE, reads standard input.

pr is the formatting front end to the printing family: pr for layout, lp or lpr to send the result to a printer.

In scripts the most common form by far is `pr -t`, which drops the headers entirely and leaves pr as a plain filter.

Options

    -t              Omit page headers and trailers, and the page padding.
                    Turns pr into a straight-through filter.
    -n              Number lines. Five columns, then a TAB.
    -h TEXT         Use TEXT as the page title instead of the file name.
    -l N            Page length in lines. Default 66, of which ten are the
                    header and trailer, leaving 56 lines of text.

Examples

    pr report.txt
        Paginate with the default header:
        #
        #
        # 2026-08-01 04:00   report.txt   Page 1
        #
        #
        # ...text...

    pr -t -n report.txt
        No header, just numbered lines.

    pr -h "Quarterly Summary" report.txt | lp
        Custom title, sent to the printer.

    grep ERROR log.txt | pr -h "Errors" -l 60 | lp

Exit status

0       Success
1       A named file could not be opened

Notes

Not implemented -- multi-column output: The -2, -3, ... options that lay text out in columns are NOT supported. Passing one is an ERROR rather than a silent no-op, so a script that depends on columns fails where you can see it instead of quietly producing single-column output that looks nearly right.

Header format: Two blank lines, the header line, two more blank lines, then the text, then five blank lines. That is pr's traditional five-and-five layout, which is what makes -l 66 give 56 usable lines.

See also

fmt, fold, nl, lp, lpr

prename back to top ↑

rename files with a Perl-style expression

Synopsis

    prename [options] EXPRESSION FILE...

Description

Applies a Perl-style expression to each FILE's name and renames the file to the result. Also installed as `file-rename`, which is the other name this tool ships under.

This is the third program called rename. Debian and Ubuntu shipped it as plain `rename` for years while Fedora shipped util-linux's, which is why a script written for one silently mangles filenames under the other. cshw gives each its own name so neither has to be guessed at: `rename` is cmd.exe's and util-linux's, and this is Perl's.

prename 's/\.htm$/.html/' *.htm
prename 'y/A-Z/a-z/' *.TXT

Two expression forms are implemented natively:

s/PATTERN/REPLACEMENT/[gi]      substitute
y/FROM/TO/                      transliterate, character for character

`tr/FROM/TO/` is accepted as a spelling of y///. Any non-alphanumeric character works as the delimiter, so s#/tmp/#/var/# needs no escaping.

PATTERN is a Perl-compatible regular expression, and REPLACEMENT uses Perl's capture syntax:

prename 's/v(\d+)/version$1/' v2.log        ->  version2.log

FROM and TO in y/// take ranges, and a shorter TO repeats its last character, both as tr does:

y/A-Z/a-z/      lower-case the name
y/0-9//         delete every digit
y/xyz/#/        every x, y or z becomes #

Options

    -n, --no-act        Change nothing, and print what would have
                        happened. Implies -v, as util-linux and
                        File::Rename both do: a dry run that says nothing
                        cannot be told apart from one that matched nothing,
                        and telling those apart is the whole point of
                        checking before a bulk rename that has no undo.
    -o, --no-overwrite  Skip a file whose new name is already taken.
    -v, --verbose       Print each rename as `old' -> `new'.
        --perl          Hand the expression to a real Perl interpreter
                        instead of running it here. See NOTES.

Examples

    prename 's/\.jpeg$/.jpg/' *.jpeg
        The everyday case.

    prename -n 's/^IMG_/photo_/' IMG_*.jpg
        Show what a batch WOULD do and change nothing. Worth doing first;
        a bulk rename has no undo.

    prename 's/(\d{4})-(\d{2})-(\d{2})/$3-$2-$1/' 2026-08-02-notes.txt
        Reorder a date with captures:  02-08-2026-notes.txt

    prename 'y/ /_/' *.txt
        Spaces to underscores.

    prename --perl 's/\d+/$&*2/e' file1.txt
        An expression this does not implement, run by Perl itself.

Exit status

0       Every file that matched was renamed.
1       At least one rename failed.
2       The expression or the command line was unusable.
A name the expression does not change is not an error. It is simply a
file the expression did not select, and it is passed over in silence.

Notes

The name only, never the path: The expression is applied to the FILE NAME and not to the directory leading to it, so `prename 's/a/b/' sub\aaa.txt` renames aaa.txt inside sub and leaves sub alone. A renamer that can silently relocate a file is not doing the job its name promises.

--perl, and why it is not automatic: Real perl-rename evals arbitrary Perl. This implements s/// and y///, which is what essentially all use of it looks like, and PCRE2 is Perl-compatible for exactly that syntax. For anything beyond it, --perl hands the whole expression to an interpreter.

That is opt-in, and deliberately so. prename NEVER delegates because
Perl happens to be installed: it fails identically on every machine
without --perl, so a script that works at one desk works at the next.
An ambient fallback would make the same command behave differently
depending on what else was installed -- the exact problem that made
pr, fold, fmt and nl built-ins instead of leaning on Git's.
Detection informs the MESSAGE, never the behaviour. When an
expression falls outside the subset, the error says whether Perl is
on PATH, present but not on PATH, or absent -- and what to type
either way. All three still require --perl.
Where it looks: PATH first, then C:\Strawberry\perl\bin,
Git's usr\bin and msys64\usr\bin. Git for Windows ships a perl and
keeps it off the system PATH, so "is Perl installed" and "is perl on
PATH" are different questions and this answers both. When --perl
runs, it reports which interpreter it used.
https://strawberryperl.com is the usual Windows Perl: it installs to
C:\Strawberry, puts perl on PATH, and bundles a compiler, so CPAN
modules build the way they do on Linux.

See also

rename, mv, sed, awk

printenv back to top ↑

print environment variables

Synopsis

    printenv
    printenv NAME
    printenv NAME...

Description

Prints the values of environment variables. Without arguments, prints all variables. With arguments, prints only the specified variables.

Options

    NAME            Specific variable(s) to print.

Examples

    printenv
        Print all environment variables.

    printenv PATH
        Print only PATH variable.

    printenv PATH HOME TEMP
        Print multiple variables.

    printenv USERNAME
        Print current username.

    printenv NONEXISTENT
        # Outputs nothing (no error)

Exit status

0       Success (variable found or all printed)
1       Variable not found (when specific name given)

Notes

Output Format: When printing a specific variable, only the value is shown (no NAME=). When printing all, format is NAME=VALUE.

Scripts: Useful in scripts to get environment values: set mypath=$(printenv PATH)

Comparison: - printenv NAME: Prints value only - echo %NAME%: Also prints value (Windows syntax) - env: Prints NAME=VALUE format

See also

env, setenv, set

printf back to top ↑

format and print arguments

Synopsis

    printf <format> [argument ...]

Description

Print the arguments under the control of <format>, in the style of the C printf function. Unlike echo, printf adds no trailing newline -- the format string controls the output exactly.

The format string may contain:

Literal text, printed as-is.
Backslash escapes:  \n  \t  \r  \a  \b  \f  \v  \\
Conversion specifications, each introduced by % and consuming one
argument:
  %s               string
  %d  %i           signed integer
  %u  %o  %x  %X   unsigned, octal, lower/upper hexadecimal
  %c               the first character of the argument
  %f %e %E %g %G   floating point
  %%               a literal percent sign
Flags (- + space # 0), a field width, and a .precision may appear
between the % and the conversion -- e.g. %-10s, %05d, %.2f.

If there are more arguments than the format consumes, the format is reused until every argument has been printed. Missing arguments are treated as an empty string or zero.

Examples

    printf '%s\n' hello
        Prints hello, followed by a newline.

    printf '%-8s%5d\n' item 42
        Prints the name left-justified in 8 columns, the number in 5.

    printf '%.2f\n' 3.14159
        Prints: 3.14

    printf '%s\n' a b c
        Prints a, b and c on three lines -- the format is reused.

Exit status

Zero on success. printf with no format argument is a usage error.

See also

echo, eval

processlist back to top ↑

list running processes

Synopsis

    processlist
    processlist [options]
    ps

Description

Displays a list of all processes currently running on the system. Shows process ID (PID), parent process ID (PPID), process name, thread count, and memory usage.

This command is essential for system monitoring, finding process IDs for the kill command, and identifying resource-heavy processes.

Options

    /v, --verbose   Show additional details including module path.

    /s, --sort NAME Sort by: name, pid, memory, threads.

    /f, --filter    Filter by process name pattern.

Examples

    processlist
        List all running processes.

    processlist /v
        Verbose listing with full paths.

    processlist | grep chrome
        Find Chrome-related processes.

    processlist /s memory
        Sort processes by memory usage.

Exit status

0       Success

Notes

Information Displayed: - PID: Process ID (unique identifier) - PPID: Parent Process ID (who started this process) - Name: Executable name - Threads: Number of threads in the process - Memory: Working set size (RAM usage)

Administrator Privileges: Some system processes may show limited information unless running as Administrator.

Process Relationships: The PPID column shows parent-child relationships between processes. A process with PPID 0 is typically a system process.

Performance: On systems with many processes, the command may take a moment to enumerate all processes.

See also

kill, jobs, top, uptime

progressdlg back to top ↑

show and drive a modeless progress dialog

Synopsis

    progressdlg <subcommand> [args]

Description

Shows a modeless progress-bar dialog and updates its state from the script. The first state-modifying subcommand creates the dialog; `progressdlg end` dismisses it.

Bound click handlers fire as coroutines, so the UI thread stays responsive. Out-of-range positions / increments are clamped to the current range rather than wrapping or erroring.

Options

    setcaption <text>
        Set the window title.
    setstatus <text>
        Set the status line below the progress bar (e.g. "12 of 100").
    setbarrange <min> <max>
        Set the bar's range. Current position clamps into the new range.
    setbarpos <n>
        Jump to an absolute position. Clamped to [min, max].
    incrementbar [<n>]
        Add n to the position (default +1; negative ok; clamped).
    button <text>
        Set the button label AND make the button visible.
    showbutton YES|NO
        Show or hide the button. `showbutton:YES` colon form also accepted.
    onbuttonclick <proc>
        Bind a script proc to the button click. The proc fires on a
        coroutine thread; the UI thread is not blocked.
    onbuttonclick cancel
        Shortcut: clicking the button destroys the dialog.
        `onbuttonclick:cancel` colon form also accepted.
    hide
        ShowWindow SW_HIDE -- the window is hidden but state is kept.
    show
        ShowWindow SW_SHOW. Creates the dialog if it doesn't exist yet.
    gethwnd
        Set $result to the dialog's HWND (0x0 when none is showing).
    end
        Destroy the dialog.

Examples

    progressdlg setcaption "Downloading..."
    progressdlg setbarrange 0 100
    progressdlg button "Cancel"
    progressdlg onbuttonclick:cancel
    foreach i (0 1 2 3 4 5 6 7 8 9)
        progressdlg setstatus "${i}0 of 100"
        progressdlg incrementbar 10
        sleep 0.5
    end
    progressdlg end

    # Bind a custom click handler instead of just dismissing:
    proc on_cancel
        share user_cancelled = 1
        progressdlg end
    endproc
    progressdlg button "Stop"
    progressdlg onbuttonclick on_cancel

Exit status

0       Success.
1       Bad subcommand, parse error, or UI thread unavailable.

Notes

Only one progress dialog exists at a time. Calling state-modifying subcommands without an existing dialog auto-creates it; subsequent calls update the live dialog via SendMessage so script-side updates from any thread are safe.

Bound click procs run as coroutines (CShellCoroutineManager). They can call back into progressdlg (e.g., setstatus) from inside the proc without deadlocking the UI thread.

See also

splash, endsplash, passworddlg, about

prompt back to top ↑

set or display command prompt

Synopsis

    prompt
    prompt FORMAT

Description

Sets or displays the shell command prompt. The prompt appears before each command you enter, typically showing the current directory and other useful information.

Options

    FORMAT          Prompt format string with special codes.

    Special codes:
    $P              Current directory path
    $G              Greater-than sign (>)
    $L              Less-than sign (<)
    $N              Current drive letter
    $D              Current date
    $T              Current time
    $S              Space
    $$              Dollar sign
    $Q              Equals sign (=)
    $H              Backspace
    $E              Escape character
    $_              Newline

Examples

    prompt
        Display current prompt format.

    prompt $P$G
        Standard prompt: "C:\Users\Me>"

    prompt [$T] $P$G
        Add time: "[14:30:25] C:\Users\Me>"

    prompt $N:$G
        Drive letter only: "C:>"

    prompt $P$_$G
        Directory on one line, > on next.

    prompt cshw $P$G
        Add prefix: "cshw C:\Users\Me>"

    prompt [$D $T]$_$P$G
        Date/time on first line, path on second.

Exit status

0       Success

Notes

Default Prompt: The default prompt is typically "$P$G" showing the current path followed by ">".

Customization: The prompt can include any text along with special codes. Use $_ for multi-line prompts.

Colors: Color codes may be supported using ANSI escape sequences with $E.

Persistence: Prompt settings are not saved between sessions. Add your prompt command to your startup script for persistence.

See also

cd, pwd, set

ps back to top ↑

Lists all the processes running on the system (alias for processlist).

No detailed man page yet — see the one-line summary above.

pushd back to top ↑

push directory onto stack and change to it

Synopsis

    pushd DIRECTORY
    pushd

Description

Saves the current directory on a stack and then changes to the specified directory. This allows you to easily return to your previous location using popd.

The directory stack enables efficient navigation between multiple working directories without losing track of where you've been.

Options

    DIRECTORY       The directory to change to.

    Without arguments, pushd swaps the top two directories on the stack.

Examples

    pushd C:\Projects
        Save current directory and change to C:\Projects.

    pushd src
        Save current directory and change to src subdirectory.

    pushd
        Swap current directory with top of stack.

    pushd D:\Backup
    # ... do work in D:\Backup ...
    popd
        Return to original directory.

Exit status

0       Success
1       Directory not found
2       Invalid argument

Notes

$dirstack: The stack is also a variable. $dirstack[1] is the CURRENT directory and deeper indices are the pushd stack with the most recently pushed first, which is both the order `dirs` prints and the order tcsh uses. It moves with `cd` as well as with pushd and popd, and `dirs -c` leaves it holding just the current directory.

pushd libs
echo "came from $dirstack[2]"

$dirstack was always empty before, so a script could read the text `dirs` prints but had no way to get at an entry.

Stack Operations: - pushd adds to the stack and changes directory - popd removes from the stack and changes back - dirs shows the current stack

Multiple Pushes: You can push multiple directories onto the stack: pushd dir1 pushd dir2 pushd dir3 # Now stack has 3 entries

The most recent push is at the top and will be the first restored by popd.

Use Cases: - Temporarily work in another directory - Navigate between related project directories - Keep track of multiple working locations

See also

popd, dirs, cd

pwd back to top ↑

print working directory

Synopsis

    pwd

Description

Prints the absolute path of the current working directory. This is the directory where relative paths are resolved from and where commands operate by default.

Examples

    pwd
        Display current directory path.

    set currentdir=$(pwd)
        Store current directory in a variable.

Exit status

0       Success (always)

Notes

The current directory is also available in the $: special variable: echo $:

pwd is equivalent to 'cd' with no arguments.

See also

cd, pushd, popd, dirs

quicsrv back to top ↑

launch and supervise quicsrv QUIC/UDP (HTTP/3) server worker processes

Synopsis

    quicsrv start <port> [/dllcfg:<file>] [/norestart]
    quicsrv status <id>
    quicsrv stop <id>
    quicsrv list

Description

The UDP/QUIC sibling of tsrvd. quicsrv runs a QUIC server in a SEPARATE process (quicsrv.exe), with cshw as the master over the same control-pipe supervision (launch, status, stop, auto-restart). QUIC runs over UDP, a different transport from tsrvd's TCP, so it is a separate command and worker. It is the foundation for HTTP/3.

Given a document root in its config, quicsrv serves HTTP/3 through the SAME static-file + CGI engine that backs http.dll's HTTP/1.1 and HTTP/2 -- a site or a CGI API behaves identically over h1, h2, and h3. Without a root it runs a minimal QUIC echo (a transport self-test).

quicsrv.exe is found next to cshw.exe. The server certificate and document root come from the /dllcfg file.

Subcommands

    start <port> [/dllcfg:<file>] [/norestart]
        Launch a QUIC worker listening on UDP <port>. /dllcfg supplies the config
        (TLS cert + optional document root / CGI). Blocks until the worker is up;
        sets $result to the new daemon id. A worker that dies unexpectedly is
        auto-restarted (with backoff); /norestart opts out.

    status <id>
        Query the worker and print its STAT line:
            STAT <accepted> <active> <running>
        (connections accepted, currently active, and 1 if listening). Also sets
        $result to that line.

    stop <id>
        Ask the worker to stop; if it overstays it is terminated. Removes it from
        the list.

    list
        Show all workers: id, port, pid, state (running/dead/failed), restart
        count (RST), and the last STAT seen.

Configuration

The /dllcfg file is key=value (# / ; comments; optional quotes on values):
    tlscert     server cert: a .pfx path, or a Windows-store subject / SHA1 thumbprint
    tlspfxpass  password if tlscert is a .pfx
    tlsstore    store name if tlscert is a store cert (default MY)
    root        document root to serve over HTTP/3 (its presence enables h3 mode)
    index       default file(s) for a directory request (default: index.html index.htm)
    listing     on = auto directory index when there is no index file
    cgiprefix   URL prefix routed to CGI scripts (e.g. /api/)
    cgidir      directory of CGI scripts
    cgiexe      CGI interpreter (default: cshw.exe next to quicsrv.exe)

Example -- serve a site plus an API over HTTP/3 on UDP 443:
    # site.conf
    tlscert    = C:\certs\server.pfx
    tlspfxpass = changeme
    root       = C:\www
    cgiprefix  = /api/
    cgidir     = C:\www\api

    quicsrv start 443 /dllcfg:site.conf

Discovery

Clients reach HTTP/3 after first seeing an Alt-Svc header over HTTP/1.1 or
HTTP/2. Set `altsvc` in the http.dll config (see Chapter 19) so its responses
advertise the quicsrv endpoint and browsers upgrade to h3.

.AUTO-RESTART
A worker that exits unexpectedly is relaunched automatically, with increasing
backoff. If it crash-loops it is marked 'failed' and left alone (visible in
`quicsrv list`); `quicsrv stop <id>` clears it. /norestart on `start` opts out.

Notes

HTTP/3 uses vendored msquic (the QUIC transport, the same one Windows' HTTP.sys uses) plus nghttp3 (framing + QPACK), shipped alongside quicsrv.exe. QUIC is UDP/443, which some locked-down networks block; clients that cannot reach h3 fall back to h2/h1.1, which is expected.

If cshw exits, the control pipe closes and the worker detects the master is gone and stops itself -- so workers are not orphaned.

Exit status

0       Success
>0      Error (worker not found, failed to launch, no cert configured, etc.)

See also

tsrvd, tcpserver, socket

rcl back to top ↑

register command library (load plugin DLL)

Synopsis

    rcl PATH
    rcl PATH PREFIX
    rcl PATH PREFIX /prefixonly
    registercmdlib PATH [PREFIX] [/prefixonly]

Description

Loads a command library DLL and registers its commands with the shell. Command libraries are DLL plugins that extend cshw with custom commands.

The DLL must export a RegisterCommandLibrary function that returns command definitions. Each command includes init, execute, and help functions following the CSHW plugin API.

Commands can be accessed with or without the namespace prefix: mylib:mycmd Explicit namespace (always works) mycmd Direct access (if no conflict)

Plugins can shadow intrinsic commands. When a plugin command has the same name as a built-in command, the plugin version takes precedence. The original command is restored when the library is unloaded.

Options

    PATH            Path to the DLL containing command definitions.
    PREFIX          Optional namespace prefix for commands.
    /prefixonly     Commands only accessible with prefix.
    /p              Short form of /prefixonly.

Examples

    rcl C:\Plugins\mylib.dll
        Load plugin with auto-detected prefix.

    rcl C:\Plugins\mylib.dll tools
        Load plugin with "tools" prefix.
        Commands available as: tools:cmd or cmd

    rcl C:\Plugins\mylib.dll tools /prefixonly
        Load with prefix required.
        Commands only available as: tools:cmd

    rcl "C:\Program Files\MyApp\plugin.dll" myapp
        Load plugin with spaces in path.

Exit status

0       Success
1       DLL not found
2       Invalid plugin format (missing RegisterCommandLibrary)
3       API version mismatch
4       Registration failed
5       Command conflicts with existing plugin command

Configuration

Command libraries can be preloaded automatically from:

INI File (cshw.ini next to cshw.exe):
    [CommandLibraries]
    C:\Plugins\mylib.dll=mylib
    C:\Plugins\tools.dll=tools:prefixonly

Registry:
    HKEY_CURRENT_USER\Software\cshw\CommandLibraries
    Value name: DLL path
    Value data: prefix

Environment Variable:
    CSHW_CMDLIBS=C:\lib1.dll;C:\lib2.dll:prefix2

Plugin Api

Plugin DLLs must export these functions:

    BOOL RegisterCommandLibrary(CShwPluginLibraryInfo** ppInfo)
        Called when plugin is loaded. Returns library info and
        command definitions.

    void UnregisterCommandLibrary(void)
        Called when plugin is unloaded. Perform cleanup here.

See CShellPluginAPI.h for the complete API specification.

Notes

Plugin Development: Include CShellPluginAPI.h from the cshw SDK to develop plugins. The header contains structures, typedefs, and convenience macros.

Shadowing: Plugins can override built-in commands with a warning. This allows extending or replacing default behavior. Originals are restored when the library is unloaded.

Security: Only load DLLs you trust. Plugin DLLs have full access to the shell process and can execute arbitrary code.

Architecture: 32-bit plugins require 32-bit cshw. 64-bit plugins require 64-bit cshw.

See also

urcl, cmdliblist, dllimport, library

rd back to top ↑

remove a directory (alias for rmdir)

Synopsis

    rd <directory>

Description

`rd` is identical to `rmdir`. See `man rmdir` for full documentation.

See also

rmdir, md, mkdir, rm

readfile back to top ↑

read a file's contents into a shell variable

Synopsis

    readfile <variable> <file>

Description

readfile reads the entire contents of <file> and stores them in the shell variable <variable>.

It is the direct way to get a file into a variable. The csh idiom `set v = \`cat file\`` also works, but backtick substitution strips the file's trailing newline and spawns a command; readfile keeps the exact content (trailing newline included) and runs in-process.

The file is read as text -- CRLF line endings are normalized to LF. For binary files, use fileblob instead.

Examples

    readfile notes settings.txt
        Load settings.txt into $notes.

    readfile body message.txt
        echo "$body"

Exit status

0 on success; non-zero if the file cannot be opened.

See also

set, cat, fileblob

readonly back to top ↑

make a variable read-only

Synopsis

    readonly <name> [= <value>]
    readonly <name1> <name2> ... <nameN>

Description

Marks one or more variables as read-only. Once a variable is read-only, further `set` / `share` / `unset` attempts against it fail with a diagnostic and a non-zero $status. The variable's value can still be read normally.

The read-only flag is per-variable, not per-namespace -- a local read-only variable disappears when its proc returns, freeing the name for re-use at the next outer scope.

Options

    <name>      Variable name(s) to mark read-only.
    <value>     Optional value to assign at the same time (only when
                one name is given).

Examples

    readonly MAX_RETRIES = 5
    set MAX_RETRIES = 99
        # ERROR: MAX_RETRIES is read-only

    readonly version = "1.0.0-alpha.1"
    echo "running $version"

    proc enforce_constants
        readonly tax_rate = 0.07
        # ...calculations using $tax_rate...
        # tax_rate disappears (and is re-assignable) when this proc returns.
    endproc

Exit status

0       Variable(s) marked read-only.
1       Variable not found, or already read-only with a conflicting
        re-declaration.

Notes

Once set, the read-only flag cannot be removed in this session. The intent is to lock down constants and configuration values that the rest of the script must treat as invariants.

See also

set, unset, local, share, declare

realpath back to top ↑

print the absolute, canonical form of a path

Synopsis

    realpath <path>

Description

Print <path> in absolute, canonical form. "." and ".." components are resolved, and a relative path is made absolute against the current working directory. Forward slashes are normalized to backslashes.

realpath is a pure path computation -- it does not consult the filesystem and <path> does not need to exist. This makes it safe for building up paths that you are about to create.

Examples

    realpath .
        Prints the current working directory.

    realpath ..
        Prints the parent of the current directory.

    realpath a/b/../c
        Prints <cwd>\a\c -- the ".." cancels "b".

Exit status

Zero on success. realpath with no path argument is a usage error; a non-zero status is also returned if the path cannot be resolved.

See also

basename, dirname, pwd

registercmdlib back to top ↑

register command library (load plugin DLL)

Synopsis

    registercmdlib PATH [PREFIX] [/prefixonly]
    rcl PATH [PREFIX] [/prefixonly]

Description

Alias for rcl. See 'man rcl' for full documentation.

See also

rcl, urcl, cmdliblist

registry back to top ↑

in-shell Windows Registry operations

Synopsis

    registry <op> KEY [options]

Description

Native Windows Registry access from cshw scripts. Named `registry` rather than `reg` so the system reg.exe stays reachable from cshw via PATH lookup. Switch syntax uses CSHW's colon form (e.g., `/v:NAME`) rather than reg.exe's space-separated form. Both `--long-form` and `-short` switches are accepted.

Options

  Operations:

    query   KEY [/v:VALUE] [/s] [/q]
        Display values and subkeys. /v: limits to one value;
        /s recurses; /q makes a missing key a silent zero-result
        success.

    get     KEY /v:VALUE [/q]
        Pipe-friendly read -- prints just the data, no header or
        type column. Suitable for `set foo = `registry get ...``.

    list    KEY [/q]              (alias: ls)
        Print just the subkey names, one per line. Lighter than
        tree, more focused than query for foreach loops.

    add     KEY /v:VALUE /t:TYPE /d:DATA [/f] [/idempotent]
        Create the key if missing and set VALUE. Repeat /d: for
        REG_MULTI_SZ lines. /f skips overwrite confirmation.

    delete  KEY [/v:VALUE] [/f]
        Delete a value (with /v:) or the entire key (without).

    copy    SRCKEY DSTKEY [/s] [/f]
        Copy a key (and optionally subkeys) to another path.

    tree    KEY [/q]
        Recursively print the subkey tree under KEY.

    export  KEY FILE [/q]
        Write the subtree to a .reg file.

    import  FILE [/f]
        Apply a .reg file to the registry.

  Key prefixes:
    HKLM\... | HKEY_LOCAL_MACHINE\...
    HKCU\... | HKEY_CURRENT_USER\...
    HKCR\... | HKEY_CLASSES_ROOT\...
    HKU\...  | HKEY_USERS\...

  Common types for /t:
    REG_SZ, REG_EXPAND_SZ, REG_MULTI_SZ, REG_DWORD, REG_QWORD,
    REG_BINARY, REG_NONE

Examples

    registry query "HKLM\SOFTWARE\Tropibyte\cshw"

    set ver = `registry get "HKLM\SOFTWARE\Tropibyte\cshw" /v:Version`
    echo "installed cshw version: $ver"

    registry add "HKCU\Software\Tropibyte\cshw" /v:Theme /t:REG_SZ /d:dark /f

    registry list "HKLM\SOFTWARE\Tropibyte"

    registry delete "HKCU\Software\Tropibyte\cshw" /v:Theme /f

    registry export "HKLM\SOFTWARE\Tropibyte" cshw-config.reg

Exit status

0       Operation succeeded (or /q used on a missing key).
1       Bad arguments or operation-specific failure (see stderr).

Notes

HKLM writes typically require admin. /q (--quiet) is useful in scripts to avoid noisy failures when a key is expected-not-present.

See also

reg, dir, where, install

rehash back to top ↑

rebuild command lookup hash table

Synopsis

    rehash

Description

Rebuilds the internal hash table that caches command locations. The shell maintains a hash of command names to paths for faster lookup. Use rehash after installing new programs to make them immediately available.

Examples

    rehash
        Rebuild command hash table.

    # After installing a new program:
    # 1. Install program (adds to PATH)
    # 2. rehash
    # 3. New program is now findable

Exit status

0       Success

Notes

When to Use: Rehash is needed when: - New programs are installed to PATH directories - PATH is modified - Programs are added/removed from PATH directories

Automatic Rehash: The shell may rehash automatically in some cases, but explicit rehash ensures the cache is current.

Performance: The hash table makes command lookups faster by avoiding repeated PATH searches. rehash rebuilds this optimization.

Shell Compatibility: rehash is traditional in csh/tcsh. Other shells use different mechanisms (bash: hash -r).

See also

hashstat, unhash, which

rename back to top ↑

rename a file, or substitute in many file names

Synopsis

    rename OLD NEW
    rename [options] FROM TO FILE...

Description

Two commands answer to the name `rename` in the wild, and the number of operands says which one you meant. They cannot be confused: the first form is always exactly two words, and the second always needs at least three, because a substitution with no files to apply it to does nothing.

With TWO operands this is cmd.exe's rename, and it is `mv`. Every option mv accepts works here, and `man mv` documents them.

rename notes.txt notes.bak

With THREE OR MORE it is util-linux's rename(1): the first occurrence of FROM in each FILE's name is replaced by TO.

rename .txt .bak *.txt

Options

These apply to the FROM TO FILE... form only. The two-operand form takes
mv's options instead.

    -a, --all           Replace every occurrence in a name, not just the
                        first.
    -n, --no-act        Change nothing, and print what would have
                        happened. Implies -v, as util-linux and
                        File::Rename both do: a dry run that says nothing
                        cannot be told apart from one that matched nothing,
                        and telling those apart is the whole point of
                        checking before a bulk rename that has no undo.
    -o, --no-overwrite  Skip a file whose new name is already taken,
                        rather than replacing it.
    -v, --verbose       Print each rename as `old' -> `new'.

Examples

    rename report.doc report-final.doc
        The everyday form. This is mv.

    rename draft.txt archive\draft.txt
        Renaming ACROSS directories, which cmd.exe refuses. See NOTES.

    rename .txt .bak *.txt
        one.txt two.txt -> one.bak two.bak

    rename -v IMG_ photo_ IMG_*.jpg
        Re-prefix a batch, reporting each one.

    rename -a _ - my_long_file_name.txt
        Every underscore, not just the first:
        my-long-file-name.txt

    rename -n -v .log .old *.log
        Show what a batch WOULD do and change nothing. Worth doing first;
        a bulk rename has no undo.

Exit status

0       Every file that matched was renamed.
1       At least one rename failed.
2       The command line was unusable.
A file whose name does not contain FROM is not an error. It is simply
a file the substitution did not select, and it is passed over in
silence.

Notes

Renaming across directories: cmd.exe refuses this -- "you cannot specify a new drive or path for your destination file" -- and so does PowerShell's Rename-Item: "Cannot rename the specified target, because it represents a path or device name." cshw allows it, because MoveFileEx allows it: a move to another directory is a rename, and a move to another VOLUME is done as a copy followed by a delete rather than refused. Declining to do something the platform supports would not make the command safer, only less useful.

The substitution form is different: it rewrites the FILE NAME only
and never the path leading to it, so `rename . _ sub\a.txt` renames
a.txt inside sub and leaves sub alone. Substituting across the whole
path is how the classic `rename . X *` accident scatters a directory,
and a renamer that can silently relocate a file is not doing the job
its name promises.

Which -n did you mean: The two forms come from different tools, and they disagree about one letter. In the two-operand form -n is mv's --no-clobber. In the substitution form it is util-linux's --no-act. The operand count has already decided which command you are running, so each -n means what it means in that command.

The third rename: A third program of this name exists on Linux -- perl-rename, also packaged as prename or file-rename -- which takes a Perl expression:

prename 's/\.htm$/.html/' *.htm
cshw implements it under those names. See `man prename`.
It deliberately does NOT answer to `rename`. Its shape is an
expression plus files, which at three or more operands is the same
shape as util-linux's FROM TO FILE..., so `rename s/a/b/ x.txt y.txt`
is genuinely ambiguous -- util-linux reads it as "replace the literal
text s/a/b/ with x.txt in the name y.txt". Operand count has already
been spent telling cmd.exe's form from util-linux's and has nothing
left to give.
Debian and Fedora historically shipped different programs under this
one name, and a script written for one silently mangles names under
the other. Giving each dialect its own name is how cshw avoids
reproducing that.

See also

mv, cp, copy, prename, file-rename

repeat back to top ↑

run a command a given number of times

Synopsis

    repeat count command [argument ...]

Description

Run a single command, with its arguments, count times in the current shell. The count must be the first argument and must be an integer.

A count of zero or a negative number runs the command zero times -- a successful no-op.

repeat runs one command. It is not a loop construct: for anything needing a loop body of multiple statements, use while, foreach, or loop instead.

Arguments

    count
        Integer number of repetitions.
    command [argument ...]
        The command to run, with any arguments.

Examples

    repeat 3 echo hi
        Prints "hi" three times.

    repeat 5 mkdir -p scratch
        Runs the mkdir five times (harmless after the first).

    repeat 0 echo nope
        Runs nothing; succeeds.

Exit status

0       The count parsed and the command ran (or count <= 0).
1       Missing arguments, or the count is not a valid integer.

Notes

The command runs in the current shell, so state changes it makes persist between iterations and after repeat returns.

See also

while, foreach, loop, eval

retproc back to top ↑

return from the current procedure with a value

Synopsis

    retproc [value]

Description

Pops the current procedure frame and publishes [value] as $result in the calling scope -- the explicit "return from a proc" verb. It is an error to call retproc outside an enclosing `proc ... endproc` block.

Companion to retshell: use retproc to unwind exactly ONE proc (bubbling up if nested); use retshell to bail all the way out to the sourcing shell. `return` is the smart variant -- it pops a proc if you are in one, otherwise behaves like retshell.

Examples

    proc square
        @ r = $1 * $1
        retproc $r
    endproc

    square 7
    echo $result        # 49

Exit status

Does not return normally -- it unwinds the proc frame. Calling it outside a
proc is an error.

See also

retshell, proc, source, exit

retshell back to top ↑

exit a sourced script without killing the shell

Synopsis

    retshell [code]

Description

Exits the current sourced script (or `cshw script.csh` subshell) with the given exit code (a numeric argument, default 0), WITHOUT terminating the calling interactive shell. Use it in cshrc or sourced setup scripts to bail on a missing precondition while keeping the user's session intact. A non-numeric argument is an error.

How the four "leave" verbs differ:

retshell : ALWAYS exits the script frame, never a proc.
retproc  : ALWAYS pops a proc frame; errors outside one.
return   : smart -- pops a proc if in one, otherwise the script.
exit     : terminates the WHOLE shell -- fine for a `cshw script.csh`
           subprocess, fatal inside a sourced file.

Examples

    # in a sourced setup script:
    if (! -f required.conf) then
        echo "required.conf missing -- skipping setup"
        retshell 1
    endif

Exit status

Does not return normally -- it unwinds the script frame with [code]
(default 0).

See also

retproc, source, exit, proc

rev back to top ↑

reverse lines character by character

Synopsis

    rev [FILE]
    command | rev

Description

Reverses the order of characters in each line. Reads from files or standard input, outputting each line with characters in reverse order.

Options

    FILE            File to process (default: stdin).

Examples

    echo "hello" | rev
        Output: olleh

    rev file.txt
        Reverse each line in file.

    echo "12345" | rev
        Output: 54321

    echo "Was it a car or a cat I saw" | rev
        Reveal palindrome patterns.

    dir /b | rev | sort | rev
        Sort by reversed names (by extension effectively).

Exit status

0       Success
1       File not found or read error

Notes

Line by Line: Each line is reversed independently. The order of lines is preserved.

Use Cases: - Checking palindromes - Reversing text for effects - Creative sorting tricks - Text manipulation puzzles

Unicode: Works with Unicode characters, reversing by character not by byte.

Comparison: - rev: Reverses characters within lines, leaving line order alone - tac: Reverses the order of lines, leaving each line alone Both exist here; `tac file | rev` does both.

See also

tac, tr, cut, sort

rm back to top ↑

remove files

Synopsis

    rm <file> [<file> ...]
    rm -r <dir> [<dir> ...]
    rm -rf <dir> [<dir> ...]
    rm /secure  <file> [<file> ...]
    rm /recycle <file> [<file> ...]
    rm --recycle <file> [<file> ...]

Description

Deletes one or more files. Registered as both 'rm' and 'del' (they share a single handler), so either name works.

By default rm permanently deletes the named files. Use /recycle (or --recycle) to send them to the Recycle Bin (recoverable), or /secure (or --secure) to overwrite the file contents with zeros before deletion.

cshw accepts both Windows-style switches and common Unix aliases. The shell's switch-extraction step rejoins lexer-split "-X" / "--X" sequences before handlers see them, so for argument purposes /secure and --secure are interchangeable.

Options

    <file>          File(s) to delete. The handler does not expand
                    wildcards itself; use the glob command for that:
                        rm `glob *.bak`

    -r, -R, --recursive, /r
                    Remove directories and their contents recursively.
                    Without it, naming a directory is an error
                    ("<name> is a directory").

    -f, --force     Do not report files that are not there. Commonly
                    combined as `rm -rf`.

    /secure, --secure
                    Overwrite the file contents with zeros (size-
                    preserving in-place write, then close, then
                    DeleteFile). Useful when you want to make recovery
                    on local storage difficult. Mutually exclusive
                    with /recycle.

    /recycle, --recycle
                    Send to the Recycle Bin instead of permanently
                    deleting. The operation FAILS rather than silently
                    falling back to permanent delete when the bin is
                    unavailable -- see NOTES on rmdir(1) for the full
                    list of refusal cases.

Examples

    rm temp.txt
        Permanently delete temp.txt.

    rm /recycle bigfile.iso
        Send bigfile.iso to the Recycle Bin (or fail if it can't fit).

    rm --recycle bigfile.iso
        Same, Unix-style spelling.

    rm /secure passwords.txt
        Overwrite passwords.txt with zeros, then delete it.

    rm a.txt b.txt c.txt
        Delete several files in one command.

Exit status

0       All files deleted successfully.
Other   At least one delete failed. Per-file errors go to stderr.

Notes

Recursion: Earlier versions of this page stated that rm "does not recurse into directories -- use rmdir for that". That was simply wrong: -r, -R, --recursive and /r have all worked, and the page documented none of them.

Junctions and symbolic links: A recursive remove deletes the LINK, never what it points at. If a tree being removed contains a junction, the junction entry is unlinked and the target directory and its contents are left completely untouched.

This is worth stating plainly because it used to be false, and the consequence was data loss: rm descended THROUGH junctions and deleted the contents of the target, so removing a tree that merely contained a link destroyed files nowhere near the tree you named, silently, and still reported success.

Long paths: Recursive removal is not limited to MAX_PATH (260 characters); a tree nested deeper than that is removed normally.

/secure is best-effort: it writes zeros to the file's currently allocated clusters, but offers no guarantee against journaling, snapshots, SSD wear-leveling, or copies that already left the disk. For real sanitization, use a tool that addresses the storage layer directly.

See also

del, rmdir, glob

rmdir back to top ↑

remove directories

Synopsis

    rmdir <dir>
    rmdir /S [/Q] <dir>
    rmdir -r [-q] <dir>
    rmdir /recycle <dir>
    rd ...

Description

Aliases: rd

Removes (deletes) a directory. By default, only empty directories can be removed. Use /S (or -r / --recursive) to recursively delete a non-empty tree, or /recycle to send the directory (empty or not) to the Recycle Bin.

cshw accepts both Windows-style switches (/S, /Q, /recycle) and the common Unix aliases (-r, --recursive, -q, --quiet, --recycle). Behind the scenes, the shell's switch-extraction step rejoins lexer-split "-X" / "--X" sequences before handlers see them, so for argument purposes /S and -r are interchangeable.

Options

    <dir>           The directory to remove.

    /S, -r, --recursive
                    Recursively delete the directory and all of its
                    contents. Permanent -- no confirmation, no Recycle
                    Bin involvement. Use with care.

    /Q, -q, --quiet
                    Suppress per-file error reporting during a recursive
                    delete. Has no effect without -r/-s.

    /recycle, --recycle
                    Send the directory to the Recycle Bin instead of
                    permanently deleting it. Handles empty and non-empty
                    directories on its own; /S is unnecessary (and
                    silently a no-op when paired). The operation FAILS
                    rather than silently falling back to permanent delete
                    when the bin is unavailable -- see NOTES.

Examples

    rmdir emptydir
        Remove an empty directory.

    rmdir /S /Q oldproject
        Permanently delete a directory tree, suppressing per-file errors.

    rmdir -r --quiet oldproject
        Same as above using Unix-style switches.

    rmdir /recycle scratch
        Send the scratch directory (empty or not) to the Recycle Bin.

    rd "Temporary Files"
        Remove a directory whose name contains a space.

Exit status

0       Success.
Other   The command's $? value is the underlying Windows error code
        from RemoveDirectoryW or, for /recycle, from IFileOperation.

Notes

Permanent deletion: /S deletes content immediately and irrevocably. There is no confirmation prompt. Double-check the path before pressing Enter.

Recycle Bin caveats: /recycle uses the Vista+ IFileOperation API with the FOFX_RECYCLEONDELETE flag set. That flag tells Windows to FAIL the operation rather than silently fall back to a permanent delete when the Recycle Bin can't accept the item: - the path is on a network/UNC share (which has no bin), - the item is larger than the bin's per-drive size budget, - the drive is removable and has no per-drive bin enabled, - or the bin is disabled by group policy on this drive. In all of those cases, the file/folder is left in place and the command returns failure. This matches the safety expectation of /recycle: "recoverable, or refuse."

In-use files: A recursive delete may fail partway through if any file in the tree is held open by another process. /Q suppresses per-file noise but does not change the behavior.

See also

mkdir, del, rm

rundllproc back to top ↑

call an exported function from a DLL

Synopsis

    rundllproc [options] DLL FUNCTION [ARGS...]
    rundllproc [options] ALIAS FUNCTION [ARGS...]
    rundllproc [options] DLL #ORDINAL [ARGS...]

Description

Loads a DLL (or reuses one previously preloaded with dllimport), resolves an exported function by name or ordinal, marshals up to 16 typed arguments and invokes it under SEH protection. The raw return value is available in %result; the printed Result line is formatted per --ret.

Options

    -v, --verbose      Verbose output: handles, function address, arg shapes.
    -r, --rundll32     Use the rundll32 entrypoint signature instead
                       (HWND, HINSTANCE, LPSTR cmdLine, int nCmdShow).
                       Args are joined into a single ANSI cmdLine.
    --ret:TYPE         Format the return value as TYPE:
                       int       (default) decimal + hex
                       hex       hex only
                       bool      TRUE / FALSE
                       hresult   HRESULT + FormatMessage text
                       wstr      dereference as LPCWSTR
                       astr      dereference as LPCSTR
                       ptr       print as pointer 0x...
                       void      suppress output

Argument Types

Each ARG is one token. Prefixes pin the type; unprefixed tokens are
auto-detected (number-shaped tokens become integers, anything else
becomes a wide-string pointer).

    i:N          Signed integer; decimal or 0xHEX. Sign-extended to a
                 pointer-sized slot.
    u:N          Unsigned / DWORD value (same width).
    p:HEX        Raw pointer-sized value (hex or decimal).
    b:0|1        BOOL. Also accepts true / false / TRUE / FALSE.
    s:STRING     Wide string (LPCWSTR). The string lives until the call
                 returns.
    a:STRING     ANSI string (LPCSTR), converted from wide via CP_ACP.
    null         Explicit NULL pointer.
    obufw:N      Allocate an N-wide-char output buffer (zeroed). After
                 the call the contents up to the first NUL are printed
                 as a wide string.
    obufa:N      Allocate an N-byte output buffer (zeroed). Decoded as
                 ANSI text up to the first NUL.
    obuf:N       Allocate an N-byte output buffer (zeroed). Hex-dumped
                 after the call (16 bytes per row).
    obufd:VALUE  Allocate a 4-byte in/out DWORD initialized to VALUE.
                 After the call the slot is reprinted as DWORD.
    obufq:VALUE  Allocate an 8-byte in/out QWORD initialized to VALUE.
                 After the call the slot is reprinted as QWORD.

Up to 16 arguments are supported.

Examples

    rundllproc kernel32.dll GetTickCount
        Call a zero-arg function. Prints the tick count.

    rundllproc kernel32.dll Sleep 250
        Pass a single integer (auto-detected).

    rundllproc user32.dll MessageBoxW 0 "Hello" "cshw" 0
        Pass two integers and two wide strings (auto-detected).

    rundllproc --ret:bool user32.dll IsWindow p:0x10010
        Tell rundllproc to format the return as TRUE/FALSE; pass an
        explicit pointer-sized value.

    rundllproc --ret:hresult ole32.dll CoInitialize null
        Print the return as an HRESULT with the FormatMessage text.

    rundllproc --ret:wstr kernel32.dll GetCommandLineW
        Treat the LPWSTR return value as a string and print it.

    rundllproc --ret:bool kernel32.dll GetComputerNameW obufw:64 obufd:64
        Real in/out call: a 64-wide-char buffer for the name and a
        4-byte DWORD pre-initialized to 64 that the function updates
        with the number of chars written.

    rundllproc --ret:bool kernel32.dll GetEnvironmentVariableW s:PATH obufw:1024 i:1024
        Read an environment variable into an output buffer; the third
        arg is the buffer size in chars (a plain int, not in/out).

    rundllproc -r shell32.dll Control_RunDLL desk.cpl
        Use the rundll32-style entrypoint (HWND, HINSTANCE, LPSTR, int).

    rundllproc mydll.dll #5
        Look up function by ordinal.

    dllimport user32.dll
    rundllproc user32 GetForegroundWindow
        Preload a DLL and refer to it by alias.

Exit status

0       Function returned (its value is in %result; check it
        yourself if the function uses a status code).
other   DLL load failed, function not found, SEH exception
        during the call, or a syntactic problem with arguments.

Notes

Safety: rundllproc invokes the function under __try / __except. Access violations and most hardware exceptions are caught and reported instead of crashing the shell -- but a corrupted process state (heap, stack walked too far, in-flight async work) can still leave the shell unhappy. Calling a function with the wrong arg shape is undefined behavior.

Calling convention: on x64 there is one calling convention so 0..16 DWORD_PTR slots cover almost any Win32 API. On x86 the helper typedefs are __cdecl; calling a __stdcall function with more args than its real arity can disturb the stack frame.

Sign extension: integer results are formatted as DWORD_PTR by default. A 32-bit signed return (e.g. lstrcmpW returning -1) will print as a large unsigned value because the upper 32 bits of the return register are zero on x64. Use --ret:hex if that is clearer, or compare against 0xFFFFFFFF.

See also

dllimport, dllunload, dlllist, winapi

say back to top ↑

print a system value (time, date, hostname, etc.) and capture it

Synopsis

    say <topic> [/fmt:<format>]

Description

Prints a single system value to stdout and stores it in $result for script use. Supports time/date formatting via wcsftime-style format strings, plus a handful of identity, location, and system-probe topics.

Options

    Time / date topics (accept /fmt:<wcsftime-format>):
      time       Current time of day  (default: HH:MM:SS.cs)
      date       Current date         (default: MM/DD/YYYY)
      datetime   Date + time          (default: YYYY-MM-DD HH:MM:SS)
      now        Alias for datetime

    Identity / location:
      hostname   Computer name
      user       Current user name
      cwd        Current working directory
      version    cshw version string
      os         Friendly OS name + build (e.g. "Windows 11 (10.0.26100)")

    System probes: additional topics like arch, build, etc. are
    surfaced as the implementation grows; `say /?` (help) lists the
    current set.

    /fmt:<format>
        wcsftime-style format string, e.g. /fmt:"%Y-%m-%d %H:%M".
        Only meaningful for the time/date topics.

Examples

    say hostname
    set host = $result

    say now /fmt:"%Y%m%d_%H%M%S"
    set stamp = $result
    echo "log_$stamp.txt"

    say version
        # prints "1.0.0.0" (or whatever the current version is)

Exit status

0       Success; $result holds the value.
1       Unknown topic or bad format.

See also

date, time, version, uname, hostname

sed back to top ↑

stream editor for filtering and transforming text

Synopsis

    sed [OPTIONS]... SCRIPT [INPUT-FILE]...
    sed [OPTIONS]... -e SCRIPT [-e SCRIPT]... [INPUT-FILE]...
    sed [OPTIONS]... -f SCRIPT-FILE [INPUT-FILE]...
    command | sed [OPTIONS]... SCRIPT

Description

sed reads text from input files (or standard input), applies a script of editing commands to each line, and writes the result to standard output. It is the canonical Unix tool for non-interactive text editing -- search- and-replace, line filtering, conditional rewriting, and stream rewriting of any kind.

cshw's sed implements a substantial GNU sed subset, with PCRE2 as the regex engine (so lookahead, lookbehind, named groups, and Unicode classes all work) and dual Windows-style and Unix-style switch spellings. It also adds Windows-specific behaviors for line endings, BOMs, and the Recycle Bin.

Options

    -n, --quiet, --silent
                Suppress automatic printing of pattern space at the end
                of each cycle. Without this, sed prints every line that
                wasn't deleted; with it, only lines explicitly printed
                by p / P / s///p / = appear.

    -e SCRIPT, --expression=SCRIPT
                Add SCRIPT to the program. Multiple -e options accumulate.

    -f FILE, --file=FILE
                Add the contents of FILE to the program. Multiple -f
                options accumulate. Mixes freely with -e.

    -E, -r, --regexp-extended
                Accepted for GNU sed compatibility. cshw's sed uses
                PCRE2 syntax unconditionally, which is a superset of
                ERE, so this flag is effectively a no-op.

    -i[SUFFIX], --in-place[=SUFFIX]
                Edit files in place. If SUFFIX is given, a backup with
                that suffix is kept (e.g. -i.bak rewrites file.txt and
                preserves file.txt.bak). Without a suffix, no backup is
                kept. The original file's encoding and line-ending
                style are preserved.

    --recycle   With -i, send the original file to the Recycle Bin
                rather than overwriting it in place. The new content is
                written to a fresh file at the original path. Provides
                a soft-delete safety net even when no backup suffix is
                given. Mutually exclusive with -c. Fails (rather than
                silently falling back to a permanent overwrite) when
                the Recycle Bin is unavailable; see NOTES.

    -c, --copy  With -i, write to a temporary file and then copy back
                rather than rename. Slower but safe across hardlink
                boundaries and OneDrive sync points.

    -s, --separate
                Treat input files as separate streams: line numbers,
                $ (last line), and the t/T branch state reset for each
                file. Without it, files are concatenated into a single
                logical stream.

    -u, --unbuffered
                Flush output after each line.

    -z, --null-data
                Use the NUL byte (ASCII 0) as the record separator, on
                OUTPUT as well as input. Useful with `find -print0`
                style producers: `find . -print0 | sed -z ... `.

                Output used to be terminated with a newline even under
                -z, which defeats the point -- a -z record may legally
                contain newlines. A record that does still picks up a
                CR on each of them when written to stdout; see the
                stdout note under "Line endings" below.

    -l N, --line-length=N
                Wrap the `l` command's output at column N. Default 70.
                0 disables wrapping.

    --posix     Disable GNU extensions (a TEXT same-line form, T, R, W,
                F, Q, z, 0~step, addr,+N, addr,~N, the e flag and
                command, replacement-string case conversion). Useful
                when porting strict POSIX scripts.

    --sandbox   Refuse to run any command that touches the host outside
                the I/O streams: r, R, w, W, e, the e flag on s, and
                the F command. The script either runs without those or
                is rejected at parse time.

    --crlf      Force CRLF line endings on output, regardless of input.

    --unix      Force LF (Unix) line endings on output. Without --crlf
                or --unix, sed auto-detects per file and writes back
                what it read.

    --debug     Annotate output with the executing command and the
                state of pattern / hold space at each cycle. Verbose;
                useful for debugging non-trivial scripts.

    --help      Print the help screen and exit.
    --version   Print version and exit.

Switch aliases:
    cshw accepts both Unix-style (-x / --xxx) and Windows-style (/x)
    spellings everywhere. So `-i.bak`, `--in-place=.bak`, and
    `/i:.bak` are all equivalent.

.SED SCRIPT LANGUAGE

A sed program consists of one or more commands, separated by newlines or
semicolons. Each command optionally begins with an ADDRESS that selects
which lines the command applies to. Comments begin with `#` and run to
end of line. The first line beginning with `#n` is equivalent to -n.

Addresses

    N           Line number N (1-based). E.g. `5d` deletes line 5.
    $           Last line of input.
    /REGEX/     Lines matching REGEX.
    \cREGEXc    Same, with custom delimiter c (any non-newline char).
                Useful when REGEX contains slashes:
                    \;/usr/local;d
    //          Empty regex re-uses the most recent regex from any
                command in the script.
    N,M         Range: from line N through line M (inclusive).
    N,$         From line N through end of input.
    /RE1/,/RE2/ From the next line matching RE1 through the next line
                matching RE2 thereafter (inclusive). Range "latches":
                once entered, stays active until RE2 matches.
    ADDR1,+N    [GNU] N lines after ADDR1 (inclusive of ADDR1).
    ADDR1,~N    [GNU] Through the next line whose number is a multiple
                of N.
    FIRST~STEP  [GNU] Every STEP lines starting at line FIRST.
                E.g. `0~2` is even lines, `1~2` is odd lines.
    0,/REGEX/   [GNU] Like /REGEX/,/REGEX/ but matches REGEX even on
                line 1 (the standard form skips line 1 when looking
                for the start of the range).
    ADDR !      Negate: the command applies to lines NOT matching ADDR.

Commands

Substitution and transliteration:
    s/RE/REPL/FLAGS
                The workhorse. Substitute RE with REPL in pattern space.
                Delimiter is whatever character follows `s` (commonly /
                or | or #). Replacement specials:
                    &       The whole match.
                    \&      A literal &.
                    \1..\9  Capture group N.
                    \n,\t   Newline, tab.
                    \r      Carriage return.
                    \\      Literal backslash.
                    \l, \u  Lowercase / uppercase the next character.
                    \L, \U  Lowercase / uppercase until \E or end.
                    \E      End \L / \U region.
                    \<nl>   Embed a literal newline in the replacement.
                Flags (any combination):
                    g       Replace all occurrences (not just the first).
                    N       Replace only the Nth occurrence (1-512).
                            Combine with g (`s/RE/REPL/3g`) to replace
                            from the Nth occurrence onward.
                    p       Print pattern space if a substitution was made.
                    w FILE  Append pattern space to FILE if substituted.
                    i, I    Case-insensitive matching.
                    m, M    Multi-line matching: ^ and $ match at
                            embedded newlines.
                    e       Execute the result as a shell command.
                            Disabled when --sandbox is in effect.
                            (cshw also disables this by default for
                            safety; pass --enable-e to opt in.)

    y/SRC/DST/  Transliterate: replace each occurrence of a character
                in SRC with the corresponding character in DST. SRC and
                DST must have the same length (after escape processing).

Pattern space output:
    p           Print the current pattern space.
    P           Print up to (and including) the first embedded newline
                in pattern space.
    =           Print the current input line number.
    l [N]       Print pattern space "unambiguously": non-printable bytes
                shown as \ooo octal, $ marks end of line, long lines
                wrap at column N (default 70 or --line-length).

Pattern space lifecycle:
    n           Print pattern space (unless -n), then read the next
                input line into pattern space. If no next line, exit.
    N           Append a newline and the next input line to pattern
                space. If no next line, behavior depends on --posix:
                strict POSIX exits without auto-printing; GNU prints
                pattern space first.
    d           Delete pattern space, start next cycle (skip auto-print).
    D           Delete up to and including the first embedded newline
                in pattern space; restart the cycle WITHOUT reading new
                input (re-runs the script on whatever's left). If no
                embedded newline, equivalent to d.

Hold space:
    h           Replace hold space with pattern space.
    H           Append \n + pattern space to hold space.
    g           Replace pattern space with hold space.
    G           Append \n + hold space to pattern space.
    x           Exchange the contents of pattern and hold space.
    z           [GNU] Zap (clear) pattern space.

Append / insert / change:
    a TEXT      Append TEXT after current line is output. TEXT can
    a\          continue across lines using a backslash at end of line.
    TEXT        The single-line `a TEXT` form is a GNU extension; the
                two-line `a\` + TEXT form is portable.
    i TEXT      Insert TEXT before current pattern space output.
    i\          Same continuation rules as `a`.
    c TEXT      Replace pattern space with TEXT. With a range address,
    c\          replaces the entire range with one copy of TEXT.

File I/O:
    r FILE      Queue contents of FILE to be output after the current
                pattern space. If FILE doesn't exist, the command is
                silently a no-op (matching GNU behavior).
    R FILE      [GNU] Queue ONE line from FILE per matching line.
                Subsequent matches read subsequent lines until EOF.
    w FILE      Write current pattern space to FILE (append after the
                first write per command per invocation; the file is
                truncated on first write).
    W FILE      [GNU] Write up to the first embedded newline of pattern
                space to FILE.
    F           [GNU] Print the name of the current input file.

Branching:
    : LABEL     Define a label.
    b LABEL     Unconditional branch to LABEL. Without a label, branch
                to end of script (skip remaining commands this cycle).
    t LABEL     Branch if any successful s/// has occurred since the
                last input line was read or the last branch.
    T LABEL     [GNU] Branch if NO successful s/// has occurred since
                the last input line was read or the last branch.

Termination:
    q [N]       Print pattern space (unless -n), drain append queue,
                exit with status N (default 0).
    Q [N]       [GNU] Quit without auto-printing or draining append
                queue.

Grouping:
    { CMDS }    Apply a block of commands as a single unit, useful with
                addresses. Group can span multiple lines.

Misc:
    #...        Comment, runs to end of line. The first line of the
                first script that begins exactly with `#n` enables -n.
    nothing     Empty commands (consecutive ; or empty -e args) are
                tolerated.

Examples

    sed 's/foo/bar/' file.txt
        Replace first 'foo' on each line with 'bar'.

    sed 's/foo/bar/g' file.txt
        Replace ALL 'foo' with 'bar' on each line.

    sed -n '5p' file.txt
        Print only line 5.

    sed '5d' file.txt
        Print everything except line 5.

    sed '/^#/d' config.ini
        Strip comment lines.

    sed -i.bak 's/old/new/g' notes.txt
        In-place edit; keep notes.txt.bak as backup.

    sed -i --recycle 's/old/new/g' notes.txt
        In-place edit; send original to the Recycle Bin (recoverable).

    sed -n '/BEGIN/,/END/p' file.txt
        Print everything between BEGIN and END markers.

    sed '5,$d' file.txt
        Keep only the first 4 lines.

    sed '0~3d' file.txt
        Delete every 3rd line.

    sed -e '/^$/d' -e 's/^[ \t]*//' file.txt
        Strip blank lines, then strip leading whitespace.

    sed 'y/abc/ABC/' file.txt
        Uppercase a, b, c.

    sed 's/.*/\U&/' file.txt
        Uppercase every line. (\U..\E is a GNU replacement extension.)

    sed -E 's/([a-z]+) ([a-z]+)/\2 \1/' names.txt
        Swap two adjacent lowercase words. -E is accepted but no-op
        (PCRE2 is the default flavor).

    sed -n '
      h
      $!d
      x
      s/.*\n//
      p
    ' file.txt
        Print only the last line (manual implementation of tail -1).

    type file.txt | sed 's/\r$//'
        Strip trailing CR (one way to convert CRLF to LF on the fly).
        Note: sed already auto-detects line endings; this is rarely
        needed in cshw.

Exit status

0       Successful completion.
1       At least one input file could not be opened.
2       Sed program syntax error, or a regex failed to compile.
N       The Q or q command exited with status N.

Notes

Regex flavor: cshw's sed uses PCRE2 (Perl Compatible Regular Expressions) for all pattern matching. This is a superset of ERE, so anything that works with `sed -E` on Linux works here. Strict GNU BRE (where (...) is literal and \(...\) is grouping) is NOT emulated -- always use ERE syntax. The -E / -r / --regexp-extended flags are accepted purely for command-line compatibility.

Line endings: Input is auto-detected per file: if the file uses CRLF on at least one line, the file is treated as CRLF and CRLFs are stripped before each line enters pattern space, then re-added on output. To force one or the other, use --crlf or --unix.

ROUND-TRIPPING IS AN -i GUARANTEE, NOT A STDOUT ONE. `sed -i` on an
LF-only file leaves it LF-only. Writing to standard output goes
through the shell's own redirection layer, which emits CRLF
regardless -- `sed 's/x/y/' unix.txt > out.txt` produces a CRLF
file. Use -i, or --unix with a tool that respects it, when the
line endings matter.

Encodings: UTF-8, UTF-16-LE, UTF-16-BE are auto-detected via byte-order mark. Files with no BOM are read as UTF-8.

The BOM is preserved by -i. It is NOT preserved through standard
output, for the same reason: the redirection layer, not sed,
decides what a redirected stream looks like on disk.

In-place editing semantics: Without --recycle and without -c, sed renames a temp file over the original. This is fast and atomic on the same drive but breaks hardlinks and may confuse OneDrive/Dropbox; use -c if either matters.

With --recycle, sed:
  1. Writes the new content to a temp file.
  2. Sends the original file to the Recycle Bin (via Vista+
     IFileOperation with FOFX_RECYCLEONDELETE, so it FAILS rather
     than silently permanent-deleting if the bin is unavailable).
  3. Renames the temp file into place.
If step 2 fails, the temp file is removed and the original is
untouched.

Recycle Bin caveats: --recycle refuses (instead of silently falling back to permanent delete) when: - the file is on a network/UNC share, - the file is larger than the per-drive Recycle Bin size budget, - the drive is removable and has no per-drive bin enabled, - or the bin is disabled by group policy on this drive. Same contract as `rm /recycle` and `rmdir /recycle`.

Sandbox mode: --sandbox rejects scripts that contain r, R, w, W, F, e, or the s///e flag at parse time, with a clear error pointing at the offending command. This is GNU-compatible behavior. Use --sandbox when running untrusted scripts, e.g. via stdin on a server.

Differences from GNU sed: * The `e` command and the s///e flag are disabled by default. Pass --enable-e to opt in. GNU sed allows them by default. * Strict BRE is not supported (PCRE2 / ERE only). * The --debug output format is similar but not byte-identical. * `l N` uses the cshw line-length when no command-local override is present; default is 70 to match GNU.

POSIX sed compatibility: --posix disables: same-line a / i / c text; `T`, `R`, `W`, `F`, `Q`, `z`; 0~step / addr,+N / addr,~N addresses; the s/// case- conversion replacement escapes (\l \u \L \U \E); the /g flag with a leading number; and embedded newlines in pattern space via N without auto-printing.

See also

awk, grep, tr, cut, type, mv

References

    GNU sed manual: https://www.gnu.org/software/sed/manual/sed.html
    POSIX sed:      IEEE Std 1003.1-2017

semaphore back to top ↑

counting semaphore

Synopsis

    semaphore <name> create <initial> [max]
    semaphore <name> acquire [/timeout:ms]
    semaphore <name> tryacquire [/timeout:ms]
    semaphore <name> release [count]
    semaphore <name> status
    semaphore <name> destroy

Description

A named counting semaphore. create takes an initial count and an optional maximum (defaulting to initial, minimum 1). acquire decrements, blocking while the count is zero; release increments. Create before use -- acquiring an unknown name is an error. semcreate is a one-line shorthand for create.

Options

    create <initial> [max]  Create with initial count (max defaults to initial).
    acquire [/timeout:ms]   Decrement, blocking; $? = 0 acquired, 1 timeout.
    tryacquire [/timeout:ms]
                            Decrement if possible (or wait up to ms);
                            $? = 0 acquired, 1 would-block. Never fatal.
    release [count]         Increment by count (default 1).
    status                  Show current count and max.
    destroy                 Remove the semaphore.

ON FAILURE
`acquire` is FATAL: a failed acquire stops the script (or the coroutine),
because the line after it is the section the permit was guarding. Use
`tryacquire [/timeout:ms]` when not getting a permit is an outcome you mean to
handle -- it reports through $? and execution continues.

Examples

    semcreate slots 3          # == semaphore slots create 3
    semaphore slots acquire
    # ... limited-concurrency work ...
    semaphore slots release

Exit status

0       Operation succeeded (acquire/tryacquire: got a slot).
>0      Acquire timeout / would block, unknown name, or bad usage.

See also

semcreate, mutex, event, barrier, channel, sync

semcreate back to top ↑

create a counting semaphore (shorthand)

Synopsis

    semcreate <name> <initial> [max]

Description

Shorthand for `semaphore <name> create <initial> [max]`. If max is omitted it defaults to initial -- a counting semaphore of fixed size. Use the semaphore command for acquire/release/status/destroy.

Examples

    semcreate slots 4
    semcreate lock 1           # a binary semaphore

Exit status

0       Created.
>0      Bad usage.

See also

semaphore, mutex, chancreate

sendmessage back to top ↑

send a Win32 message to a window (synchronous)

Synopsis

    sendmessage <hwnd> <msg> [<wParam> [<lParam>]]

Description

Calls SendMessageW(hwnd, msg, wParam, lParam) and blocks until the window's WndProc returns. The LRESULT is captured in $result as a long.

`msg` accepts symbolic WM_* names (case-insensitive) or hex/decimal numbers. Symbolic names are looked up in CSHW's built-in table; any message not in the table can still be addressed by number.

Options

    <hwnd>      Target HWND in hex or decimal. Must satisfy IsWindow().
    <msg>       Symbolic name (WM_CLOSE, wm_command, WM_USER, ...) or
                a number (0x10, 16, 273, ...).
    <wParam>    WPARAM. Default 0. Hex or decimal.
    <lParam>    LPARAM. Default 0. Hex or decimal.

    Recognized symbolic names include: WM_NULL, WM_CREATE, WM_DESTROY,
    WM_MOVE, WM_SIZE, WM_ACTIVATE, WM_SETFOCUS, WM_KILLFOCUS,
    WM_ENABLE, WM_SETTEXT, WM_GETTEXT, WM_GETTEXTLENGTH, WM_PAINT,
    WM_CLOSE, WM_QUIT, WM_SHOWWINDOW, WM_ACTIVATEAPP, WM_SETCURSOR,
    WM_GETMINMAXINFO, WM_NOTIFY, WM_KEYDOWN, WM_KEYUP, WM_CHAR,
    WM_SYSKEYDOWN, WM_SYSKEYUP, WM_COMMAND, WM_TIMER, WM_HSCROLL,
    WM_VSCROLL, WM_MOUSEMOVE, WM_LBUTTONDOWN, WM_LBUTTONUP,
    WM_RBUTTONDOWN, WM_RBUTTONUP, WM_USER.

Examples

    # Simulate a button click on control id 100 in window $w:
    sendmessage $w WM_COMMAND 100 0

    # Programmatically close a window:
    sendmessage $w WM_CLOSE

    # Set a window's text:
    # (lParam is the address of the string in real Win32 -- not safe
    # to pass a script string here; use SetWindowText via winapi for
    # text-setting.)

Exit status

0       Success. $result holds the LRESULT as a long.
1       Bad HWND, unparseable message, or bad wParam/lParam.

Notes

SendMessage is synchronous and may block on a misbehaving window. For fire-and-forget delivery use `postmessage`.

See also

postmessage, bindevent, createwindow

seq back to top ↑

print sequence of numbers

Synopsis

    seq LAST
    seq FIRST LAST
    seq FIRST INCREMENT LAST

Description

Prints a sequence of numbers from FIRST to LAST, with optional INCREMENT. Useful for loops, generating test data, and numeric sequences.

Options

    LAST            Print 1 to LAST.
    FIRST LAST      Print FIRST to LAST.
    FIRST INCREMENT LAST
                    Print from FIRST to LAST by INCREMENT.

    -s STRING       Use STRING as separator (default: newline).
    -w, --equal-width
                    Pad with leading zeros for equal width.
    -f FORMAT       Use printf-style FORMAT.

Examples

    seq 5
        Output: 1 2 3 4 5 (one per line)

    seq 3 7
        Output: 3 4 5 6 7

    seq 0 2 10
        Output: 0 2 4 6 8 10 (by 2)

    seq 10 -1 1
        Output: 10 9 8 7 6 5 4 3 2 1 (countdown)

    seq -s ", " 5
        Output: 1, 2, 3, 4, 5

    seq -w 1 100
        Output: 001 002 ... 099 100 (padded)

    seq 0.5 0.5 3
        Output: 0.5 1.0 1.5 2.0 2.5 3.0 (decimals)

    # Loop example:
    foreach i ($(seq 1 10))
        echo "Iteration $i"
    endforeach

Exit status

0       Success
1       Invalid arguments

Notes

Floating Point: seq supports decimal numbers: seq 0.1 0.1 1.0

Negative Numbers: Both negative values and counting down work: seq -5 5 # -5 to 5 seq 5 -1 -5 # 5 down to -5

Use in Loops: seq is commonly used with foreach: foreach n ($(seq 1 100)) process_item $n endforeach

Generating Data: Useful for creating test files: seq 1000000 > numbers.txt

See also

foreach, loop, echo

service back to top ↑

manage Windows services

Synopsis

    service list
    service start NAME
    service stop NAME
    service restart NAME
    service status NAME
    service info NAME

Description

Manages Windows services - background processes that run independently of user sessions. Can list, start, stop, restart, and query service status.

Options

    Subcommands:

    list            List all services with their status.
    start NAME      Start a stopped service.
    stop NAME       Stop a running service.
    restart NAME    Stop then start a service.
    status NAME     Show current status of a service.
    info NAME       Display detailed service information.

    Options:
    /all            Include all services (not just running).

Examples

    service list
        List running services.

    service list /all
        List all services including stopped ones.

    service status spooler
        Check print spooler status.

    service start wuauserv
        Start Windows Update service.

    service stop wuauserv
        Stop Windows Update service.

    service restart spooler
        Restart print spooler (common fix for printing issues).

    service info bits
        Show detailed info about BITS service.

Exit status

0       Success
1       Service not found
2       Access denied (need Administrator)
3       Service operation failed

Notes

Administrator Required: Starting and stopping services requires Administrator privileges. Run the shell as Administrator for service management.

Service Names: Use the short service name, not the display name. For example: - wuauserv (not "Windows Update") - spooler (not "Print Spooler") - bits (not "Background Intelligent Transfer Service")

Use 'service info' to see both names.

Common Services: wuauserv Windows Update spooler Print Spooler w32time Windows Time bits Background Intelligent Transfer Service dnscache DNS Client wsearch Windows Search

Startup Types: Services can be set to start automatically, manually, or be disabled. This command doesn't modify startup types.

See also

processlist, kill, reg

set back to top ↑

set or display shell variables

Synopsis

    set
    set NAME=VALUE
    set NAME VALUE

Description

Sets a shell variable or displays all currently defined shell variables. Without arguments, displays all shell variables and their values.

Shell variables are used for storing values that can be referenced later in commands and scripts using the $NAME syntax. Variables can hold strings, integers, or floating-point numbers, and CSHW automatically tracks the type.

Variables set with 'set' are shell-local and do not affect the system environment. Use 'setenv' to modify environment variables.

Options

    NAME            The variable name. Must start with a letter or underscore,
                    followed by letters, digits, or underscores.

    VALUE           The value to assign. Can be:
                    - String: "hello world" or hello
                    - Integer: 42, -17, 0x1F (hex)
                    - Float: 3.14, -2.5, 1.0e-3

Examples

    set
        Display all shell variables.

    set count=10
        Set variable 'count' to integer 10.

    set name="John Doe"
        Set variable 'name' to a string with spaces.

    set pi=3.14159
        Set variable 'pi' to a floating-point number.

    set path C:\Tools
        Set variable 'path' (alternative syntax without =).

    echo $count
        Display the value of variable 'count'.

    set result=$?
        Store the last command's exit code in 'result'.

    set files=$(dir /b *.txt)
        Store command output in a variable (command substitution).

Exit status

0       Success
1       Invalid variable name
2       Syntax error

Environment

Shell variables are separate from environment variables. Changes made with 'set' do not affect the process environment. Use 'setenv' for that purpose.

Notes

Variable Naming Rules: - Must start with a letter (a-z, A-Z) or underscore (_) - Can contain letters, digits (0-9), and underscores - Names are case-sensitive ($Name != $name)

Type Inference: CSHW automatically determines variable type based on the assigned value: - Integers: whole numbers (42, -17, 0xFF) - Floats: numbers with decimal points (3.14) or exponents (1e-3) - Strings: everything else ("hello", paths, etc.)

Use 'vartype' command to check a variable's inferred type.

Special Variables: $? Exit code of the last command $: Current working directory $$ Process ID of the shell

The variable model: csh has exactly ONE kind of variable -- a list of words. `set e = one` and `set e = ( one )` are the same thing, a list of one word, and `$e[1]` is that word in both. There is no separate "string" type to choose: a string IS a one-word list.

cshw keeps that and adds types on top -- Integer, Float, Array, Associative -- which is what makes `@` arithmetic, `vartype` and `hash` possible. The addition does not change the model: SUBSCRIPTING is by WORD on every variable, whatever its type.

set e = one          $e[1] is "one",  $#e is 1,  $e[2] is empty
set e = ( one )      identical in every respect
set c = "two words"  $c[1] is "two words" -- quoting makes one word

`$e[1]` used to return `o` for a scalar -- the first CHARACTER -- so the subscript meant one thing on an array and another on a string, decided by a type the script could not see.

To index CHARACTERS, use the substring form, which is separate syntax for a separate job and is 0-indexed (csh word indices are 1-indexed; both conventions are kept as they are rather than one being bent to match the other):

set s = "hello world"
${s:0:1}  ->  h        one character
${s:0:5}  ->  hello    a substring
${s:6}    ->  world    to the end
$s[1]     ->  hello world

Arrays: Parentheses make an ARRAY, however many words are inside them:

set one  = ( alpha )          $#one is 1, $one[1] is "alpha"
set many = ( alpha beta )     $#many is 2
set none = ( )                $#none is 0
set flat = alpha              a scalar, not a one-element array

That "however many" is the point. The array/scalar decision used to be made on the word count, so a group holding exactly one word became a string and `$one[1]` read `a` -- the first character. `$#one` said 1 either way, so the shape of a variable depended on how many files a glob matched: `set files = ( *.txt )` was an array with two matches and a string with one.

A signed number inside a group is one element: `set n = ( -42 )` holds "-42", while `set n = -42` is a scalar.

Shell settings (csh/tcsh compatibility): These are OPTIONS the shell reads, set with the bare `set NAME` form or given a value. Each one changes behaviour; none is decorative.

noclobber      Refuse to truncate an existing file with `>`.
noglob         Turn filename substitution off.
nonomatch      A pattern matching nothing is passed through as
               typed instead of being an error. Without it, csh's
               default applies: the shell reports "PATTERN: No
               match.", abandons the command line and sets the
               status to 1, so `rm *.tmp` in a directory with no
               .tmp files refuses rather than handing rm a literal
               asterisk.
verbose        Echo each command line as typed, before expansion.
echo           Echo each command line after expansion. Together with
               verbose this shows what a line turned into as well as
               what it was. Both write to stderr, so a trace never
               lands in a backtick capture. Distinct from the `echo
               on`/`echo off` command, which gates the prompt.
printexitvalue Report "Exit N" on stderr after a command that exited
               non-zero. A pipeline reports once, for the pipeline.
echo_style     Which echo this is: bsd (the default), sysv, both or
               none. See `man echo`.
cdpath         A list of directories `cd` searches when a bare
               relative name is not in the current directory.
histchars      The character that introduces a history reference,
               replacing `!`. csh takes two characters, the second
               for `^old^new` quick substitution; only the first is
               honoured, because quick substitution is not
               implemented. History substitution runs at the
               interactive prompt only, so this has no effect on a
               script -- a `!` in a script file is always literal.

Shell values (published, not read): path PATH as a word list -- `foreach d ($path)` is the idiom dirstack The directory stack. $dirstack[1] is the CURRENT directory and deeper indices are the pushd stack, newest first, exactly as in tcsh. shell The running shell's own executable prompt The prompt string home The home directory cwd The current directory owd The directory before the last one that MOVED version cshw's version; osversion the Windows version

See also

unset, vartype, setenv, unsetenv, echo

setenv back to top ↑

set environment variable

Synopsis

    setenv NAME VALUE
    setenv NAME=VALUE

Description

Sets or modifies an environment variable. Unlike shell variables (set), environment variables are inherited by child processes and can affect system behavior.

Options

    NAME            Environment variable name.
    VALUE           Value to assign.

Examples

    setenv PATH "C:\Tools;%PATH%"
        Prepend C:\Tools to PATH.

    setenv JAVA_HOME "C:\Program Files\Java\jdk-17"
        Set JAVA_HOME for Java applications.

    setenv DEBUG 1
        Set a debug flag.

    setenv MY_APP_CONFIG "C:\Config\app.ini"
        Set application-specific variable.

Exit status

0       Success
1       Invalid name
2       Error setting variable

Notes

Inheritance: Environment variables are inherited by child processes: - Programs started from the shell see these variables - Use for configuration that programs expect

Shell vs Environment Variables: - set: Shell-local, not inherited by children - setenv: Environment, inherited by children

Persistence: setenv changes only affect the current session and child processes. To permanently set environment variables, use System Properties or the Windows 'setx' command.

Common Variables: PATH Executable search path HOME User's home directory TEMP/TMP Temporary file directory USERNAME Current user name

Case Sensitivity: Environment variable names are case-insensitive on Windows (PATH = Path = path).

See also

unsetenv, set, env, printenv

sha1sum back to top ↑

compute SHA-1 message digest

Synopsis

    sha1sum FILE...
    command | sha1sum

Description

Computes and displays the SHA-1 hash (160-bit) of files. SHA-1 produces a 40-character hexadecimal digest.

Options

    FILE            One or more files to hash.

    -c FILE         Check SHA-1 sums against a checksum file.

Examples

    sha1sum file.txt
        Compute SHA-1 hash.

    sha1sum *.zip
        Hash multiple files.

    sha1sum -c checksums.sha1
        Verify files against checksums.

    echo "test" | sha1sum
        Hash a string.

Exit status

0       Success (or all checksums verified)
1       Checksum mismatch
2       File not found

Notes

Piped input: With no file operand and a redirected stdin, sha1sum hashes what it is given and prints "-" in the filename column, the way GNU does. The stream is treated as text and hashed as UTF-8, so the digest matches what GNU produces for the same text. An interactive shell with nothing piped in gets the usage message rather than blocking on the terminal.

Security Warning: SHA-1 is cryptographically broken and should NOT be used for security purposes. Collisions have been demonstrated.

Acceptable uses for SHA-1: - Legacy system compatibility - Non-security checksums - Git commit IDs (uses SHA-1)

For security, use SHA-256 or SHA-512 instead.

Output Format: da39a3ee5e6b4b0d3255bfef95601890afd80709 filename

Git Compatibility: Git uses SHA-1 for commit and object IDs, so sha1sum can be useful when working with Git internals.

See also

sha256sum, sha512sum, md5sum

sha256sum back to top ↑

compute SHA-256 message digest

Synopsis

    sha256sum FILE...
    command | sha256sum

Description

Computes and displays the SHA-256 hash (256-bit) of files. SHA-256 is cryptographically secure and produces a 64-character hexadecimal digest.

SHA-256 is recommended for security applications including file integrity verification and digital signatures.

Options

    FILE            One or more files to hash.

    -c FILE         Check SHA-256 sums against a checksum file.

Examples

    sha256sum installer.exe
        Compute SHA-256 hash.

    sha256sum *.zip > checksums.sha256
        Generate checksums for all ZIP files.

    sha256sum -c checksums.sha256
        Verify files against checksums.

    echo "secret" | sha256sum
        Hash a string (includes newline).

Exit status

0       Success (or all checksums verified)
1       Checksum mismatch
2       File not found

Notes

Piped input: With no file operand and a redirected stdin, sha256sum hashes what it is given and prints "-" in the filename column, the way GNU does. The stream is treated as text and hashed as UTF-8, so the digest matches what GNU produces for the same text. An interactive shell with nothing piped in gets the usage message rather than blocking on the terminal.

Output Format: e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 file.txt

Security: SHA-256 is part of the SHA-2 family and is considered cryptographically secure. It's suitable for: - File integrity verification - Digital signatures - Password hashing (with proper salting) - Blockchain and cryptocurrency

Verification: Software downloads often provide SHA-256 checksums. Always verify: sha256sum -c downloaded.sha256

Speed: SHA-256 is slower than MD5 but provides much stronger security.

See also

sha512sum, sha1sum, md5sum

sha512sum back to top ↑

compute SHA-512 message digest

Synopsis

    sha512sum FILE...
    command | sha512sum

Description

Computes and displays the SHA-512 hash (512-bit) of files. SHA-512 produces a 128-character hexadecimal digest. Part of the SHA-2 family, it offers the highest security level.

Options

    FILE            One or more files to hash.

    -c FILE         Check SHA-512 sums against a checksum file.

Examples

    sha512sum file.txt
        Compute SHA-512 hash.

    sha512sum important.doc > important.sha512
        Save checksum to file.

    sha512sum -c checksums.sha512
        Verify files against checksums.

    sha512sum *.iso
        Hash multiple ISO files.

Exit status

0       Success (or all checksums verified)
1       Checksum mismatch
2       File not found

Notes

Piped input: With no file operand and a redirected stdin, sha512sum hashes what it is given and prints "-" in the filename column, the way GNU does. The stream is treated as text and hashed as UTF-8, so the digest matches what GNU produces for the same text. An interactive shell with nothing piped in gets the usage message rather than blocking on the terminal.

Security: SHA-512 is the strongest SHA-2 variant. Suitable for: - High-security file integrity - Cryptographic applications - Password hashing (with salt)

Output Format: cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e file

Performance: SHA-512 is actually faster than SHA-256 on 64-bit systems due to using 64-bit operations natively.

When to Use: - Maximum security requirements - Long-term archives - Cryptographic protocols - When 256 bits isn't enough

See also

sha256sum, sha1sum, md5sum, shasum

shadow back to top ↑

hide a built-in so a program of the same name runs instead

Synopsis

    shadow
    shadow COMMAND ...

Description

Takes a built-in out of command lookup without destroying it, so a program of the same name on PATH answers instead.

With no arguments, lists the commands currently shadowed.

cshw ships built-ins that share a name with real Windows programs -- `tree` and `vol` are both `%SystemRoot%\System32` executables as well, and Git ships its own `dir.exe`. The built-in wins, which is the point: a command means the same thing on every machine regardless of what else is installed. `shadow` is how you say "not this time" for one name, without giving up that guarantee for everything else.

shadow tree
tree            now runs C:\Windows\System32\tree.com
unshadow tree
tree            the built-in again

Nothing is deleted. The command is set aside and `unshadow` puts it back, so a shadow is always reversible -- see NOTES.

Options

    COMMAND     A built-in to hide. Several may be named at once.
                Shadowing something already shadowed is not an error.

Examples

    shadow
        List what is currently hidden.

    shadow dir
        Hand `dir` to whatever is on PATH -- Git's dir.exe, say, if you
        want GNU coreutils behaviour for one session.

    shadow tree vol
        Two at once.

    unshadow -a
        Undo all of it.

Exit status

0       Every named command was hidden, or already was.
1       At least one name could not be.

Notes

When nothing replaces it: `shadow` hides a command, it does not swap one in. If no program on PATH answers to the name, the name simply stops resolving:

shadow vol
vol     ->  ERROR: 'vol' is not recognized ...
That is the intended answer rather than an oversight. Hiding a
built-in with nothing behind it SHOULD leave the name unresolvable;
quietly falling back to the thing you just hid would make the command
meaningless.

What cannot be shadowed: Only built-ins. An alias is not one -- use `unalias` for those, which shadow will tell you. And `shadow` refuses to shadow itself or `unshadow`, because those are the way back.

Reversibility: The built-in is moved into the same store `rcl` uses when a plugin claims an intrinsic's name, and is restored from it. Nothing in cshw can permanently remove a built-in; a shell one bad line away from being unusable is not a shell anyone should have to trust.

Scope: A shadow lasts for the session. Put the line in a startup script to make it persistent -- and if a startup script has shadowed more than you remember, `shadow` with no arguments says what, and `unshadow -a` clears the lot.

Finding out what will run: `which` reports the RESOLUTION, not the built-in, and says why:

which tree                  tree: cshw built-in command
shadow tree ; which tree    C:\Windows\System32\tree.com (shadowed intrinsic)
A shadowed name is never described as a built-in, because it is no
longer what runs.

See also

unshadow, which, where, alias, unalias, rcl

share back to top ↑

assign a variable in the global namespace (write-through)

Synopsis

    share <name> = <value>
    share <name>[<index>] = <value>
    share <name>{<key>}   = <value>

Description

Like `set`, but always writes through to the global variable namespace even when called from inside a proc or a coroutine.

Inside a proc, plain `set foo = 1` creates a procedure-local variable that disappears on return. Inside a coroutine, plain `set` creates a coroutine-local variable invisible to the main script thread.

`share` bypasses both. The variable is created/updated in the global namespace, visible to every thread and outliving any proc / coroutine scope.

Options

    <name>      Variable name. Same naming rules as `set`.
    <value>     The value to assign. Supports the same forms `set`
                supports: integer literals, floats, quoted strings,
                command-substitution, etc.

Examples

    # Coroutine writes a result back to the main thread:
    share _ready = 0
    proc worker
        sleep 2
        share _ready = 1
    endproc
    spawn worker
    while ($_ready == 0)
        sleep 0.1
    end
    echo "worker finished"

    # Procedure publishes a return value via a shared var instead of
    # the conventional $result -- useful when multiple values matter:
    proc compute
        share answer  = 42
        share message = "ok"
    endproc
    compute
    echo "$answer / $message"

Exit status

0       Variable was written.
1       Syntax error or readonly violation.

Notes

`share` is the canonical way for a coroutine to communicate results back to the main script thread. Coroutine-local `set` writes are isolated by design; `share` is the explicit opt-in to break that isolation.

WM_CLOSE veto handlers (see `bindevent`) similarly use `share` to report user intent back to the script that's waiting on the dialog.

See also

set, unset, local, declare, readonly

shasum back to top ↑

compute or verify a SHA hash with a selectable algorithm

Synopsis

    shasum FILE...
    shasum -a BITS FILE...
    shasum BITS FILE...
    shasum [-a BITS] -c CHECKSUM-FILE...
    command | shasum [-a BITS]

Description

Computes SHA digests, or verifies files against a saved list of them. Without -a the algorithm is SHA-256.

Output is the standard checksum-file format -- the hex digest, two spaces, the filename -- so `shasum *.exe > sums.txt` followed later by `shasum -c sums.txt` is the whole workflow. The format is shared with md5sum, sha1sum, sha256sum and sha512sum, which are the same tool with the algorithm fixed.

`shasum BITS FILE...` -- the bit size as a bare leading operand -- is cshw's own older spelling and still works. It is read as an algorithm only when it names one AND a file follows it, so `shasum 256` on its own hashes a file named 256.

Options

    FILE            File(s) to hash.

    -a BITS         Algorithm to use:
                    1       SHA-1 (160-bit) - NOT SECURE
                    256     SHA-256 (256-bit) - DEFAULT
                    384     SHA-384 (384-bit)
                    512     SHA-512 (512-bit)

    -c, --check     Treat each operand as a checksum file and verify the
                    files it lists. Prints "name: OK" or "name: FAILED"
                    per entry. Combine with -a if the file was written
                    with something other than SHA-256.

Examples

    shasum file.txt
        Compute the SHA-256 digest.

    shasum -a 512 file.txt
        Compute the SHA-512 digest.

    shasum -a 1 legacy.dll
        SHA-1, for checking against an old published digest.

    shasum *.exe > checksums.txt
        Record digests for every executable here.

    shasum -c checksums.txt
        Verify them again later.

    shasum -c checksums.txt > /dev/null || echo "something changed"
        A mismatch sets the status without ending the script.

    shasum 256 file.exe
        The older cshw spelling; same as -a 256.

Exit status

0       Every digest computed, or every checked file matched.
1       A checked file did not match, a file could not be read, or
        the bit size was not one shasum supports.

Notes

No SHA-224: Earlier versions of this page listed 224. CryptoAPI, which supplies the digests, has no SHA-224 provider, so `-a 224` is refused rather than silently answered with a different algorithm.

A mismatch is a result, not a failure: -c reports each file and sets the exit status to 1 if any did not match. It does not add a command-failure line on top of that, so `shasum -c sums.txt || handle_it` reads cleanly.

Piped input: With no file operand and a redirected stdin, shasum hashes what it is given and prints "-" in the filename column, the way GNU does. The stream is treated as text and hashed as UTF-8, so `echo secret | shasum` yields the same digest GNU produces for the same line. An interactive shell with nothing piped in still gets the usage message rather than blocking on the terminal.

Algorithm selection: - SHA-1: legacy only, broken cryptographically - SHA-256: recommended for most uses, and the default - SHA-384: truncated SHA-512 - SHA-512: widest digest available here

See also

sha256sum, sha512sum, sha1sum, md5sum

shift back to top ↑

shift positional parameters

Synopsis

    shift
    shift N

Description

Shifts positional parameters ($1, $2, etc.) to the left. After shift, $2 becomes $1, $3 becomes $2, and so on. The old $1 is discarded.

Options

    N               Number of positions to shift (default: 1).

Examples

    # Script: process_args.csh
    # Called with: process_args a b c d

    echo $1     # a
    shift
    echo $1     # b (was $2)
    shift
    echo $1     # c (was $3)

    # Shift by 2:
    shift 2
    echo $1     # d (was $4)

    # Process all arguments:
    while ($# > 0)
        echo "Processing: $1"
        shift
    endwhile

Exit status

0       Success
1       No arguments to shift

Notes

Use in Scripts: shift is commonly used in scripts to process command-line arguments one at a time, especially when argument count varies.

$# Variable: $# contains the argument count. After shift, $# decreases by 1.

Processing Options: Common pattern for handling options: while ($# > 0) if ($1 == "-v") set verbose=1 else if ($1 == "-o") shift set output=$1 else # Regular argument process $1 endif shift endwhile

Empty Arguments: Shifting when no arguments remain produces an error.

See also

set, echo

shutdown back to top ↑

shutdown, restart, or log off the system

Synopsis

    shutdown [options]
    shutdown /s
    shutdown /r
    shutdown /l

Description

Shuts down, restarts, or logs off the computer. Can also abort a pending shutdown operation. Requires appropriate privileges for shutdown/restart.

Options

    /s              Shutdown the computer.
    /r              Restart the computer.
    /l              Log off the current user.
    /h              Hibernate (if supported).
    /a              Abort a pending shutdown.
    /t SECONDS      Time delay before action (default: 30).
    /f              Force running applications to close.
    /c "MESSAGE"    Display a comment/reason (max 512 chars).
    /p              Immediate poweroff (no timeout, no warning).

Examples

    shutdown /s
        Shutdown in 30 seconds.

    shutdown /r /t 0
        Immediate restart.

    shutdown /l
        Log off current user.

    shutdown /s /t 60 /c "Maintenance in 1 minute"
        Shutdown in 60 seconds with message.

    shutdown /a
        Cancel pending shutdown.

    shutdown /r /f
        Restart, force-closing applications.

    shutdown /h
        Hibernate the system.

    shutdown /p
        Immediate power off (no delay).

Exit status

0       Success (operation initiated)
1       Access denied
2       Invalid argument

Notes

Force Close: Without /f, shutdown waits for applications to close gracefully. With /f, applications are forcefully terminated (may lose unsaved work).

Abort Window: During the timeout period, use 'shutdown /a' to cancel.

Privileges: Shutdown and restart require appropriate privileges. On domain computers, group policy may restrict these operations.

Remote Shutdown: Windows supports remote shutdown with /m \\computer option, though this may require additional configuration.

Scheduled Tasks: For scheduled shutdowns, consider using Task Scheduler instead of leaving a shutdown command pending.

See also

exit, logout, service

sleep back to top ↑

pause the current thread of execution for a duration

Synopsis

    sleep DURATION

Description

Blocks the current thread of execution for DURATION. In the interactive shell that means the prompt pauses; inside a coroutine it pauses just that coroutine while the rest of the shell keeps running.

DURATION is a number with an optional unit suffix. Fractional values are accepted and rounded to the nearest millisecond. The maximum duration is about 49 days (the 32-bit millisecond cap that Win32 Sleep() uses).

Options

    DURATION    Number + optional unit. Recognised suffixes:
                  ms                milliseconds
                  s   (default)     seconds
                  m                 minutes
                  h                 hours
                  d                 days
                Long-form aliases (millisecond, sec, secs, min, mins,
                hour, hours, day, days) are also accepted.

Examples

    sleep 5
        Pause for 5 seconds (default unit is seconds).

    sleep 0.5
        Pause for 500 milliseconds.

    sleep 100ms
        Pause for 100 milliseconds.

    sleep 2s
        Pause for 2 seconds.

    sleep 5m
        Pause for 5 minutes.

    sleep 1.5h
        Pause for one hour and thirty minutes.

    sleep 1d
        Pause for 24 hours.

    # In a polling loop:
    while (1)
        processlist | grep myprogram
        sleep 5s
    endwhile

    # Inside a coroutine -- only this coroutine pauses:
    corunproc myproc {
        sleep 1m
        echo "minute elapsed"
    }

Exit status

0       Success.
1       Missing argument, negative value, unknown unit, or
        duration over the 49-day cap.

Notes

sleep blocks the calling thread (Win32 Sleep). For per-coroutine pauses, just call sleep inside the coroutine -- it will not block the shell.

To pause until a system event rather than a time, write the polling loop yourself with a 'while' and a short sleep, or use 'corunproc' to do the waiting on a worker.

To prevent the *system* from sleeping while a long task runs, see 'suspend keepawake'.

See also

suspend, timeout, time, corunproc

socket back to top ↑

low-level socket operations

Synopsis

    socket <subcommand> [args...]

Description

Provides low-level TCP and UDP socket operations for network programming. Sockets are identified by names (user-assigned or auto-generated like "sock1").

Subcommands

    create [-4|-6] [--dual] [--keep-mapped] tcp|udp [name]
        Create a new socket. Returns socket id in $result.
        Type can be 'tcp' (SOCK_STREAM) or 'udp' (SOCK_DGRAM).
        Default family is IPv4. Pass -6 (or --ipv6) for an IPv6 socket.

        --dual
            For IPv6 sockets, clear IPV6_V6ONLY before bind so the same
            socket accepts both IPv6 and IPv4 clients. Implies -6; using
            it with -4 is an error.

        --keep-mapped
            By default, when a v4 client connects to a dual-stack v6
            listener, its address is stripped from ::ffff:a.b.c.d to plain
            a.b.c.d in 'socket info' and 'socket accept' output, and the
            accepted socket's family is reported as IPv4. Pass this flag
            to keep the on-the-wire v6 form. Only meaningful with --dual.

    bind <sock> [addr] <port>
        Bind socket to address and port. Address defaults to the wildcard for
        the socket's family: 0.0.0.0 for IPv4, :: for IPv6. Quote IPv6 literals
        on the command line: socket bind v6sock "::1" 8080

    listen <sock> [backlog]
        Start listening for connections. Backlog defaults to SOMAXCONN.

    accept <sock> [/timeout:ms] [name]
        Accept an incoming connection. Returns new socket id in $result.
        Use /timeout to specify maximum wait time in milliseconds.

    connect <sock> <host> <port> [/timeout:ms]
        Connect to a remote server. Host can be IP address or hostname.

    send <sock> <data>
        Send data through the socket. Data is sent as UTF-8.

    recv <sock> [maxbytes] [/timeout:ms]
        Receive data from socket. Result stored in $result.
        Default maxbytes is 4096. Timeout returns empty string (not error).

    close <sock> | /all
        Close a socket or all open sockets.

    list
        Display all open sockets with their state and addresses.

    info <sock>
        Show detailed information about a socket.

    select <sock> r|w|e [/timeout:ms]
        Check if socket is readable (r), writable (w), or has errors (e).
        Multiple modes can be combined (e.g., "rw"). Result contains matched modes.

Options

    /timeout:ms, /t:ms
        Specify timeout in milliseconds for blocking operations.

Examples

    # Simple TCP server
    socket create tcp server
    socket bind server 8080
    socket listen server
    set client (socket accept server)
    socket recv $client
    echo "Received: $result"
    socket send $client "Hello back!"
    socket close $client
    socket close server

    # Simple TCP client
    socket create tcp
    socket connect $result localhost 8080
    socket send $result "Hello server"
    socket recv $result
    echo "Response: $result"
    socket close $result

    # UDP example
    socket create udp sender
    socket connect sender 192.168.1.100 5000
    socket send sender "UDP message"
    socket close sender

    # Check socket readability with timeout
    socket select mysock r /timeout:5000
    if $result == "r"
        socket recv mysock
    endif

Exit status

0       Success
>0      Error (check $errorlevel for WSA error code)

Errors

    10048   WSAEADDRINUSE - Address already in use
    10060   WSAETIMEDOUT - Connection timed out
    10061   WSAECONNREFUSED - Connection refused

See also

tcpserver, tcpclient, fetch

sort back to top ↑

sort lines of text

Synopsis

    sort [options] FILE
    command | sort [options]

Description

Sorts lines of text alphabetically or numerically. By default, sorts in ascending order using the entire line as the sort key.

Options

    FILE            File to sort.

    -r, --reverse   Sort in descending order.
    -n, --numeric   Sort numerically instead of alphabetically.
    -u, --unique    Remove duplicate lines (output unique lines only).
    -f, --ignore-case
                    Ignore case when sorting.
    -t CHAR         Use CHAR as field delimiter.
    -k N            Sort by field N (1-based).

Examples

    sort names.txt
        Sort file alphabetically.

    sort -r names.txt
        Sort in reverse order.

    sort -n numbers.txt
        Sort numerically (1, 2, 10 not 1, 10, 2).

    sort -u data.txt
        Sort and remove duplicates.

    dir /b | sort
        Sort directory listing.

    sort -t, -k2 data.csv
        Sort CSV by second column.

    sort -f words.txt
        Case-insensitive sort.

    type log.txt | grep ERROR | sort -u
        Get unique sorted error lines.

Exit status

0       Success
1       File not found
2       Error

Notes

Stability: The sort is stable - equal elements maintain their relative order.

Numeric vs Alphabetic: Without -n, "10" sorts before "2" (alphabetically). With -n, "2" sorts before "10" (numerically).

Memory: Large files are sorted in memory. Very large files may require significant RAM.

Locale: Sort order may be affected by system locale settings.

See also

uniq, wc, grep

source back to top ↑

execute commands from a file in the current shell

Synopsis

    source FILE
    . FILE

Description

Reads and executes commands from FILE in the current shell environment. Unlike running a script normally, source executes in the current shell, so variable changes and alias definitions persist after the file executes.

This is the standard way to load configuration files and define procedures.

Options

    FILE            Script file to execute.

Examples

    source config.csh
        Load configuration file.

    source ~/.cshrc
        Load shell startup file.

    source functions.csh
        Load procedure definitions.

    . mysetup.csh
        Short form using dot notation.

    source env_setup.csh && echo "Environment loaded"
        Load and confirm.

Exit status

Returns the exit status of the last command executed in the file.

Notes

Variable Scope: Variables set in the sourced file become available in the current shell. This is different from running a script as a subprocess.

Use Cases: - Loading configuration: source ~/.cshrc - Setting up environment: source project_env.csh - Defining procedures: source myfunctions.csh

Startup Scripts: On interactive startup, CSHW loads a startup file if present. It first looks for %USERPROFILE%\.cshrc. If that file is missing, it falls back to %APPDATA%\cshw\cshwrc.

Error Handling: If an error occurs during sourcing, subsequent commands in the file may still execute. Use 'exit' in the script if fatal errors should stop execution.

Dot Command: The '.' command is an alias for 'source' (UNIX tradition): . config.csh

See also

set, alias, library, exit

spawn back to top ↑

start another cshw instance in a new console window

Synopsis

    spawn
    spawn [options] -c COMMAND
    spawn [options] -k COMMAND
    spawn [options] SCRIPT [ARGS...]

Description

Launches a second cshw in its own console window. The new shell re-invokes the same binary that is running now -- a development build spawns itself, not whatever `cshw` happens to resolve to on PATH.

The new shell inherits the current working directory and the exported environment. Shell-local variables, aliases, completions and job state do NOT cross; the new shell reads .cshrc and settings.csh for itself, exactly as if it had been launched from Explorer.

With no arguments, spawn opens a plain interactive window. With -c the new shell runs COMMAND and closes; with -k it runs COMMAND and then stays at an interactive prompt, which is what makes `spawn -k "cd C:\proj"` useful.

spawn is deliberately not called "fork". Windows has no fork: there is no address-space copy and no shared descriptor table between the two shells. What you get is a fresh process, which is what CreateProcess provides.

Options

    -c COMMAND      Run COMMAND in the new shell, then exit.
    -k COMMAND      Run COMMAND in the new shell, then stay interactive.
    SCRIPT [ARGS]   Run a script file in the new shell.

    /d PATH         Start in PATH instead of the current directory.
                    Also accepted as /d:PATH.
    /title TEXT     Set the new window's title.
    /min            Start the window minimized.
    /max            Start the window maximized.
    /wait           Wait for the new shell to exit and adopt its exit
                    code as $status.
    /here           Reuse this console instead of opening a window. The
                    nested shell shares this shell's standard handles and
                    any redirection in effect. Implies /wait.

Options must appear BEFORE -c or -k. Like cmd's /C and /K, everything after
-c or -k is taken as the command, so a switch written after it becomes part
of the command text rather than an option to spawn.

Examples

    spawn
        Open a new interactive cshw window in the current directory.

    spawn -k "cd C:\proj"
        New window already parked in C:\proj.

    spawn -c "ls -l"
        Run a command in a new window, then close it.

    spawn /title "build log" -k "tail -f build.log"
        Named window following a log file.

    spawn /min /wait build.cshw release
        Run a script minimized, block until it finishes, adopt its status.

    spawn /here
        Nested shell in the current console; `exit` returns to the parent.

    spawn /here -c "exit 4" || echo "child failed"
        /here implies /wait, so $status carries the child's 4 and the
        || chainer fires.

Exit status

0       New shell started (or, with /wait, exited 0)
N       With /wait or /here, the child shell's own exit code
1       Could not start the new shell
2       Unknown option

Notes

Exit status: Without /wait, spawn returns as soon as the child is created and prints the new process id, so a script can kill it later. It does not wait, and the child's eventual exit code is not observable. With /wait or /here, the child's exit code is published to $status verbatim -- not flattened to 1 -- so chainers and `if` tests see the real value.

Redirection: A new console window has its own standard handles, so redirecting spawn's output does not capture the child's. Use /here when you want the child to write into this shell's stdout, or have the child redirect internally: spawn -c "ls -l > listing.txt"

Environment inheritance: setenv writes through to the process environment block, so exported variables reach the child. `set` variables are shell-local and do not. Pass those explicitly: spawn -k "set target = $target"

See also

start, exec, jobs, bg, fg, kill

splash back to top ↑

show a modeless splash dialog during a long-running step

Synopsis

    splash [<mode> [<duration_ms>]]

Description

Puts up a modeless splash dialog and returns immediately, so the script keeps running with the splash on top. Typical use: cover a long step (downloads, init, build) so the user sees something other than a console.

Dismiss with `endsplash`, or wait for the timer when mode=timed.

Calling `splash` while one is already showing is a no-op.

The modeless splash ignores mouse clicks and the OK / close buttons -- only `endsplash` (or the timer, for mode=timed) dismisses it.

Options

    <mode>          One of:
                      splash    (default)  title + tagline
                      timed                same look; auto-dismisses
                                            after <duration_ms>
                      about | verbose | logo | none
    <duration_ms>   Only meaningful for mode=timed. Default 3000 ms.
                    The script does NOT wait for the timer to fire.

Examples

    splash
        Show the default splash. Dismiss with endsplash later.

    splash logo
        Show the logo variant.

    splash timed 5000
        Show for 5 seconds and auto-dismiss. Script continues immediately.

    splash
    # ... do long-running work ...
    endsplash

Exit status

0       Success (or splash already showing -- treated as success).
1       UI thread not available (non-interactive mode without it).

Notes

The modal counterpart is `testsplash` -- internal/dev-only and not part of the public surface.

See also

endsplash, about, progressdlg, passworddlg

splitpath back to top ↑

print the components of a path, one per line

Synopsis

    splitpath <path>

Description

Split <path> into its individual directory/name components and print each on its own line. Both forward slashes and backslashes are recognized as separators.

Empty components -- from a leading separator or doubled separators -- and a leading drive specifier such as "C:" are skipped, so what comes back is just the list of names.

This pairs naturally with foreach: the output drops straight into a word list.

foreach part (`splitpath C:\dir\subdir\file.txt`)
    echo $part
end

splitpath is a pure text operation; it does not touch the filesystem.

Examples

    splitpath C:\dir\subdir\subdir2
        Prints three lines: dir, then subdir, then subdir2

    splitpath /usr/lib/file
        Prints three lines: usr, then lib, then file

Exit status

Zero on success. splitpath with no path argument is a usage error.

See also

basename, dirname, realpath

start back to top ↑

start a program or open a file

Synopsis

    start [OPTIONS] PROGRAM [ARGS...]
    start [OPTIONS] FILE
    start [OPTIONS] URL

Description

Starts a program in a new window, opens a document with its associated application, or opens a URL in the default browser. Unless /wait is given, the shell does not wait for the program to complete.

Options

    PROGRAM         Program to execute.
    FILE            File to open with associated application.
    URL             Web address to open in browser.
    ARGS            Arguments to pass to the program.

    /min            Start window minimized.
    /max            Start window maximized.
    /wait           Wait for the program to terminate and adopt its exit
                    code as $status.
    /b              Run on this console instead of creating a new window.
                    The child shares this shell's stdio, so its output can
                    be piped or captured.
    /d PATH         Set starting directory. Also accepted as /d:PATH.
    /i              Pass the environment cshw was launched with, ignoring
                    any setenv changes made since.

Options must appear BEFORE the target; the first non-switch argument is
taken as the program, file or URL, and everything after it is passed
through as arguments.

/b and /i take the direct process-launch path rather than the Windows
shell association layer, so they apply to executables only -- not to
documents or URLs.

Examples

    start notepad
        Open Notepad in new window.

    start notepad document.txt
        Open document in Notepad.

    start document.docx
        Open Word document (with associated app).

    start https://www.google.com
        Open URL in default browser.

    start /max excel report.xlsx
        Open Excel maximized with file.

    start /wait setup.exe
        Run installer and wait for completion.

    start /d "C:\Projects" cmd
        Open command prompt in specific directory.

    start /min background.exe
        Start program minimized.

    start /b /wait cmd /c "echo hi"
        Run on this console and capture its output; without /wait the
        shell returns before the child writes anything.

    start /wait setup.exe || echo "installer failed"
        /wait publishes the real exit code, so chainers branch on it.

Exit status

0       Success (program started)
N       With /wait, the program's own exit code
1       Program/file not found
2       Error starting program or unknown option

Notes

New Window: start creates a new window/process. The shell continues immediately unless /wait is specified.

File Associations: For documents, Windows opens the associated application: - .docx -> Microsoft Word - .pdf -> PDF reader - .html -> Web browser

Path Spaces: If the path contains spaces and you use a title, put the title first: start "My Title" "C:\Program Files\App.exe"

Without Title: Use empty quotes for title if path has spaces: start "" "C:\Path With Spaces\program.exe"

Background Programs: Use start for launching programs that should run independently of the shell session.

See also

exec, sudo, jobs

stat back to top ↑

display file status information

Synopsis

    stat [-c FORMAT | --format=FORMAT | --printf=FORMAT] FILE...

Description

Displays detailed information about files including size, timestamps, attributes, and owner. Provides more detail than dir for individual files.

With -c, prints only what FORMAT asks for, which is what makes stat usable from a script:

set bytes = `stat -c %s report.txt`

Options

    -c FORMAT       Print FORMAT for each file instead of the full listing,
    --format=FORMAT followed by a newline.
    --printf=FORMAT The same, WITHOUT the trailing newline.
    FILE            One or more files to examine.

Format

    %n  file name, as given          %N  file name in quotes
    %s  size in bytes                %F  regular file / directory /
    %h  number of hard links             symbolic link
    %i  file index (inode)           %d  volume serial (device)
    %U  owner account name           %G  group account name
    %A  permissions, as ls -l        %a  permissions, octal
    %y  modification time            %Y  ...as seconds since the epoch
    %x  access time                  %X  ...as seconds since the epoch
    %w  creation (birth) time        %W  ...as seconds since the epoch
    %%  a literal %

    \n, \t, \r and \\ are the escapes you would expect.

    An unrecognised specifier is an error, not a passthrough -- a format
    that quietly printed %Q because nobody implemented it would be the
    sort of silent success this shell tries not to have.

    %A and %a are a Windows APPROXIMATION of a Unix concept, computed the
    same way `ls -l` computes its mode column: read-only clears `w`, and
    an executable extension (.exe, .com, .bat, .cmd, .ps1, .cshw) sets
    `x`. They agree with `ls -l` by construction. Windows has no mode
    bits, so no better answer exists -- see `man chmod`.

Examples

    stat document.txt
        Display full status of document.txt.

    stat -c %s report.txt
        Just the size, for a script to capture.

    stat -c "%n is %s bytes, a %F, mode %A (%a)" report.txt
        report.txt is 6 bytes, a regular file, mode -rw-r--r-- (644)

    stat --printf="%Y\n" build.log
        Modification time as an epoch second, for comparing two files.

    stat *.exe
        Show status of all executables.

    stat "C:\Program Files"
        Examine a directory.

Exit status

0       Success
1       File not found
2       Access denied

Notes

Information Displayed: - Full path - File size in bytes - Creation time - Last modification time - Last access time - File attributes (read-only, hidden, system, archive) - Owner (if accessible)

Attributes: R = Read-only H = Hidden S = System A = Archive D = Directory L = Reparse point (symlink/junction)

Timestamps: Windows maintains three timestamps per file. Access time updates may be disabled on some systems for performance.

See also

dir, attrib, type

stop back to top ↑

suspend a running job

Synopsis

    stop %JOBID
    stop PID

Description

Suspends (pauses) a running job or process. The job remains in memory but stops executing until resumed with 'bg' or 'fg'.

Stopping a job that is ALREADY stopped succeeds and does nothing, so a script can reach a known state without checking first. It used to report "failed to suspend job N" at status 1, which reads as though the job were still running and the shell could not touch it.

Stopping a job that has already finished is an error, and says so rather than blaming a suspend that could never have worked.

Options

    %JOBID          Job number from 'jobs' command (prefixed with %).
    PID             Process ID to suspend.

Examples

    stop %1
        Suspend job number 1.

    stop %2
        Suspend job number 2.

    jobs
        # [1]  Running     longprocess.exe
        # [2]  Running     another.exe
    stop %1
    jobs
        # [1]  Stopped     longprocess.exe
        # [2]  Running     another.exe

Exit status

0       Success
1       No such job
2       Cannot stop job

Notes

Difference from Kill: - stop: Pauses the process (can be resumed) - kill: Terminates the process (cannot be resumed)

Resuming: Use 'fg %JOBID' to resume in foreground. Use 'bg %JOBID' to resume in background.

Interactive Stop: Pressing Ctrl+Z in the terminal also stops the foreground process.

System Processes: Some system processes cannot be stopped without Administrator privileges.

See also

jobs, bg, fg, kill

strings back to top ↑

extract printable strings from files

Synopsis

    strings [options] FILE
    strings FILE

Description

Extracts and displays sequences of printable characters from files, particularly useful for examining binary files. Finds text embedded in executables, DLLs, and other binary formats.

Options

    FILE            File to examine.

    -n LENGTH       Minimum string length (default: 4).
    -a              Scan entire file (default).
    -t FORMAT       Print offset (d=decimal, o=octal, x=hex).

Examples

    strings program.exe
        Find strings in an executable.

    strings -n 10 binary.dat
        Find strings at least 10 characters long.

    strings -t x malware.exe
        Show strings with hex offsets.

    strings file.dll | grep -i password
        Search for password-related strings.

    strings *.exe | grep -i "http://"
        Find URLs in executables.

    strings image.jpg
        Find metadata text in images.

Exit status

0       Success
1       File not found
2       Read error

Notes

Default Behavior: By default, strings extracts ASCII sequences of 4+ characters. This catches most meaningful text while filtering noise.

Security Analysis: strings is valuable for malware analysis and reverse engineering. It can reveal: - Hardcoded URLs, IPs, filenames - Error messages and debug strings - Function names and API calls - Embedded credentials (don't do this!)

Binary Analysis: Combined with grep, strings is a quick way to search binary files for specific patterns: strings malware.bin | grep -E 'http|ftp|password'

See also

hexdump, grep, file

sudo back to top ↑

run command as Administrator

Synopsis

    sudo COMMAND [ARGS...]

Description

Runs a command with elevated (Administrator) privileges. On Windows, this triggers User Account Control (UAC) to request elevation. The command runs in a new elevated process.

Options

    COMMAND         The command to run elevated.
    ARGS            Arguments to pass to the command.

Examples

    sudo notepad C:\Windows\System32\drivers\etc\hosts
        Edit hosts file (requires admin).

    sudo reg add HKLM\SOFTWARE\Test /v Key /d Value
        Modify HKLM registry (requires admin).

    sudo service start wuauserv
        Start Windows Update service.

    sudo netsh firewall show config
        View firewall configuration.

    sudo cmd /c "net user Administrator /active:yes"
        Enable Administrator account.

Exit status

Returns the exit code of the elevated command, or:
1       UAC cancelled by user
2       Error launching elevated process

Notes

UAC Prompt: Windows displays a User Account Control prompt asking for permission. If denied, the command does not run.

New Window: The elevated command typically runs in a new console window, as Windows doesn't allow mixing elevation levels in one console.

When Needed: Administrator rights are required for: - Modifying system files - HKEY_LOCAL_MACHINE registry changes - Service management - Network configuration - Installing software system-wide

Already Elevated: If the shell is already running as Administrator, sudo simply runs the command normally.

Security: Be cautious with sudo. Only elevate commands you trust and understand.

See also

service, reg, kill

suspend back to top ↑

manage system power state from the shell

Synopsis

    suspend
    suspend status
    suspend keepawake [on | off]
    suspend keepawake while DURATION

Description

suspend manages the system's power state. It does NOT pause shell execution -- use 'sleep' for that.

The only state currently managed is "keepawake", which prevents the system from going to sleep or hibernating while cshw is running. The underlying mechanism is SetThreadExecutionState with the ES_CONTINUOUS | ES_SYSTEM_REQUIRED | ES_AWAYMODE_REQUIRED flags, refreshed by a background thread every fifteen seconds.

When cshw exits, the keepawake state is automatically released and normal Windows power management resumes -- so even if you forget to turn it off, the system goes back to its configured timeouts as soon as you close the shell.

Options

    status                  Print 'keepawake: on' or 'keepawake: off'.
                            (Running 'suspend' alone is the same.)
    keepawake               With no further argument: print current
                            state. Same as 'status'.
    keepawake on            Start preventing system sleep / hibernation.
    keepawake off           Stop preventing system sleep / hibernation.
    keepawake while DUR     Turn keepawake on, sleep DUR (same syntax
                            as the sleep command), then restore the
                            previous keepawake state. Useful for "stay
                            awake for the next two hours then revert".

Examples

    suspend keepawake on
        Don't let the box sleep while cshw runs.

    suspend keepawake off
        Restore default power management.

    suspend keepawake while 2h
        Stay awake for two hours, then go back to whatever the
        keepawake state was before.

    suspend status
        Query: prints 'keepawake: on' or 'keepawake: off'.

Exit status

0       Success.
1       Syntax error (unknown subcommand, unknown argument,
        missing DURATION, or bad DURATION).

Notes

This is a runtime hint to the OS, not a registry change. It does the same thing as the powercfg block:

powercfg /change standby-timeout-ac 0
powercfg /change standby-timeout-dc 0
powercfg /change monitor-timeout-ac 0
...

except (a) it auto-restores when cshw exits, (b) it doesn't persist across reboots, and (c) it doesn't require admin. It will not override group policy on locked-down machines.

The 'suspend' command used to also pause the shell for a duration (e.g. 'suspend 5 minutes'). That role has moved to 'sleep', which now accepts unit suffixes ('sleep 5m'). 'suspend' with a bare number prints a redirect message.

See also

sleep, timeout

sync back to top ↑

list and destroy synchronization objects

Synopsis

    sync list [type]
    sync destroy <type> <name>
    sync destroyall

Description

Manages the process-wide table of named synchronization objects created by mutex, event, semaphore, barrier, and channel. list shows them (optionally filtered to one type); destroy removes a single object; destroyall clears the whole table. type is one of: mutex, event, semaphore, barrier, channel.

Options

    list [type]            List all objects, or just those of type.
    destroy <type> <name>  Destroy one named object.
    destroyall             Destroy every synchronization object.

Examples

    sync list
    sync list channel
    sync destroy mutex m
    sync destroyall

Exit status

0       Always (destroy of a missing name reports "not found").
>0      Bad usage / unknown type.

See also

mutex, event, semaphore, barrier, channel

tac back to top ↑

concatenate and print files in reverse line order

Synopsis

    tac [file...]
    tac [/reverse | --reverse]

Description

Reverse-order concatenation, the cat-spelled-backwards companion to `cat`. With multiple files the FILE ORDER is kept and each file's lines are reversed within it, which is what GNU tac does: `tac a b` prints a's lines reversed, then b's lines reversed.

Internally, `tac` is `cat` with reverseDefault=true; it shares all the cat infrastructure, so options that work for `cat` (line numbering, BOM-aware encoding detection, etc.) work for `tac`.

Options

    /reverse, --reverse
        Cancel the default reversal -- effectively makes tac behave
        like cat for that one invocation. Mainly useful in scripts
        that conditionally choose tac or cat.

    file...
        Files to read. Reads stdin when none are given.

    See `man cat` for the full set of formatting flags (-n, -b, -s,
    -E, -T, -v, -A, -e, -t, -q, -u) -- all available for tac too.

Examples

    tac log.txt
        Print log.txt with the lines reversed.

    cat log.txt | tac
        Same effect via pipe.

    tac access.log error.log
        access.log's lines reversed, then error.log's. The files stay in
        the order given; only the lines inside each are reversed.

Exit status

0       Success.
1       File not found or I/O error.

See also

cat, rev, head, tail

tail back to top ↑

output the last part of files

Synopsis

    tail [options] FILE
    tail -n COUNT FILE
    command | tail [options]

Description

Outputs the last part of files or piped input. By default, prints the last 10 lines. Essential for viewing log files and monitoring output.

Options

    FILE            File to read from.

    -n COUNT        Output the last COUNT lines (default: 10).
    -COUNT          Shorthand for -n COUNT (e.g., -20).

    -n +COUNT       Output starting from line COUNT (skip first COUNT-1 lines).

    -c COUNT        Output the last COUNT bytes instead of lines.

    -f, --follow    Keep file open and output new lines as they're appended.
                    Useful for monitoring log files. Press Ctrl+C to stop.

Examples

    tail file.txt
        Display last 10 lines of file.txt.

    tail -n 20 log.txt
        Display last 20 lines.

    tail -50 error.log
        Display last 50 lines (shorthand).

    tail -f access.log
        Monitor log file in real-time (follow mode).

    tail -n +5 data.txt
        Output everything starting from line 5.

    processlist | tail -n 5
        Show last 5 processes in list.

    tail -c 256 binary.dat
        Show last 256 bytes.

Exit status

0       Success
1       File not found
2       Read error

Notes

Follow Mode: The -f flag is particularly useful for monitoring log files. The shell keeps the file open and displays new content as it's written. Use Ctrl+C to exit follow mode.

Log Monitoring: Common pattern for monitoring logs: tail -f /var/log/app.log | grep -i error

Line Selection: Use -n +N to skip the first N-1 lines and output the rest. This is useful for skipping headers: tail -n +2 data.csv # Skip header row

See also

head, type, wc, grep

tar back to top ↑

archive files

Synopsis

    tar -c [-z] [-v] -f ARCHIVE [-C DIR] FILES...
    tar -x [-z] [-v] -f ARCHIVE [-C DIR]
    tar -t [-v] -f ARCHIVE

Description

Creates, extracts, or lists the contents of tar archives. Supports both plain tar and gzip-compressed (.tar.gz or .tgz) archives.

tar (tape archive) is the standard UNIX archive format. CSHW's tar implementation provides core functionality for bundling files together.

Options

    Operation mode (one required):
    -c, --create    Create a new archive.
    -x, --extract   Extract files from archive.
    -t, --list      List archive contents.

    Modifiers:
    -f ARCHIVE      Specify archive filename (required).
    -z, --gzip      Use gzip compression/decompression.
    -v, --verbose   Verbose output (list files processed).
    -C DIR          With -x, extract into DIR.
                    With -c, read the FILES from DIR and store them under
                    the names given -- `tar -cf a.tar -C build out`
                    archives `out`, not `build/out`, which is what makes
                    the archive unpack where it was meant to.

Examples

    tar -cvf backup.tar Documents/
        Create archive of Documents folder.

    tar -czvf backup.tar.gz Documents/
        Create gzip-compressed archive.

    tar -tvf backup.tar
        List contents of archive.

    tar -xvf backup.tar
        Extract archive in current directory.

    tar -xvf backup.tar -C /restore
        Extract to specific directory.

    tar -xzvf backup.tar.gz
        Extract gzip-compressed archive.

    tar -cvf project.tar *.cpp *.h Makefile
        Archive specific files.

Exit status

0       Success
1       Archive error (corrupt, not found)
2       I/O error
3       Invalid arguments

Notes

Archive Format: CSHW's tar uses standard POSIX ustar format, compatible with other tar implementations.

Gzip Compression: The -z flag enables gzip compression. Files are typically named .tar.gz or .tgz when compressed.

Permissions: Windows doesn't have UNIX permissions. CSHW stores basic attributes but permission bits may not be meaningful on Windows.

Long Filenames: The ustar format supports filenames up to 255 characters. Longer names may be truncated.

Symbolic Links: Windows symbolic links (created with mklink) are archived as their target paths.

Large Files: Files up to 8GB are supported. Larger files require extended formats not currently implemented.

See also

copy, mv, gzip

tc back to top ↑

time how long a command takes to run

Synopsis

    tc [/v] command [argument ...]

Description

Run a command and report how long it took. Everything after tc -- and an optional leading /v switch -- is taken from the raw command line and run fresh in the current shell, so the command keeps its own switches, quoting, pipes, and redirection.

tc records a high-resolution timestamp before the command starts and again after it finishes, then prints the elapsed wall-clock time in seconds.

With /v (verbose), tc also prints the command line that ran and its exit status.

tc is transparent: after it returns, $status and $? hold the exit status of the command that ran, not tc's own -- so tc can be dropped in front of any command without disturbing status checks or && / || chains.

The elapsed time is also stored, in seconds, in the shell variable $timecount, so a script can read the measurement and act on it.

Examples

    tc sort big.txt
        Sorts the file, then prints e.g. "tc: 1.204 s".

    tc /v grep -r needle .
        Runs the recursive grep, then prints the command line, the
        elapsed time, and the exit status.

    tc sleep 2
        Prints roughly "tc: 2.001 s".

Exit status

The exit status is that of the timed command -- tc is transparent. Running tc with no command is a usage error.

Notes

The elapsed time is wall-clock time, so it includes any time the command spent waiting on I/O, other processes, or the system.

See also

eval, repeat

tcpclient back to top ↑

one-shot TCP client

Synopsis

    tcpclient <host> <port> [options]

Description

One-shot TCP client that connects to a server, optionally sends data, optionally receives a response, and closes the connection.

This is a convenience command for simple request/response patterns. For more complex interactions or persistent connections, use the low-level socket command instead.

Options

    -4 | --ipv4
        Force IPv4. Errors out if the host can't be reached over IPv4.

    -6 | --ipv6
        Force IPv6. Errors out if the host can't be reached over IPv6.
        Quote IPv6 literals: tcpclient "::1" 8080

    /send:"data"
        Send the specified data after connecting.
        Quotes are optional but recommended for data with spaces.

    /recv
        Receive response data. Result is stored in $result.

    /timeout:ms
        Connection and receive timeout in milliseconds.
        Default is 5000 (5 seconds).

Family Selection

When neither -4 nor -6 is given, the family is auto-detected. A literal IP
address picks its own family. A hostname is resolved with the OS resolver
under AF_UNSPEC; whichever family it returns first wins (this honors the
system's preference rules, e.g. RFC 6724 / Windows source-address policy).

Examples

    # Check if a server is listening (connect test)
    tcpclient localhost 8080
    if $? == 0
        echo "Server is up"
    else
        echo "Server is down"
    endif

    # Send data and receive response
    tcpclient localhost 8080 /send:"hello" /recv
    echo "Response: $result"

    # HTTP GET request
    tcpclient example.com 80 /send:"GET / HTTP/1.0\r\nHost: example.com\r\n\r\n" /recv
    echo $result

    # With custom timeout
    tcpclient slow-server.com 8080 /timeout:30000 /recv

    # Check website availability
    tcpclient google.com 443
    if $? == 0
        echo "Google is reachable"
    endif

Notes

localhost is IPv6 first: On a current Windows box `localhost` resolves to ::1 before 127.0.0.1, while tcpserver binds IPv4 unless told otherwise. So pairing a plain `tcpserver 8080 handler` with `tcpclient localhost 8080` connects to nothing and waits for the timeout. Either name the v4 address -- `tcpclient 127.0.0.1 8080` -- or start the server dual-stack with `tcpserver --dual 8080 handler`, which binds both families.

Escape Sequences: Use \r\n for carriage return + line feed (HTTP requires this). Example: "GET / HTTP/1.0\r\n\r\n"

HTTPS: This command does not support SSL/TLS. For HTTPS, use the fetch command instead.

Response Handling: The command waits for the connection to close or timeout before returning all received data. For streaming responses, use the low-level socket commands.

Exit status

0       Success
>0      Connection failed, timeout, or error

See also

tcpserver, socket, fetch

tcpserver back to top ↑

start a TCP server

Synopsis

    tcpserver <port> <handler_proc> [options]

Description

Starts a TCP server that listens on the specified port and calls a handler procedure for each incoming connection.

The server creates a socket, binds to the port, and enters an accept loop. For each accepted connection, it calls the handler procedure with the client socket ID as an argument.

By default, the server runs indefinitely. Use /max or /timeout to limit.

Options

    -4 | --ipv4
        Bind the IPv4 wildcard 0.0.0.0 (default).

    -6 | --ipv6
        Bind the IPv6 wildcard ::. By default this listens IPv6-only;
        accepted clients must reach the server over IPv6.

    --dual
        Bind ::, but clear IPV6_V6ONLY so the same socket accepts both
        IPv6 and IPv4 clients. Implies -6; conflicts with -4.

    --keep-mapped
        With --dual, v4 peers normally appear as plain a.b.c.d in
        'socket info' and the accepted socket's family is reported as
        IPv4. Pass --keep-mapped to leave the on-the-wire ::ffff:a.b.c.d
        form intact and report the family as IPv6 instead.

    /max:N
        Accept at most N connections, then exit.

    /timeout:ms
        Stop after timeout milliseconds with no new connections.

    /once
        Same as /max:1 - accept one connection and exit.

    /mthread
        Handle connections CONCURRENTLY. The default server processes one
        connection at a time (the handler runs inline in the accept loop);
        with /mthread the server is backed by the cshw::net::CServer engine,
        which accepts on a dedicated thread and runs each handler on its own
        worker thread, so slow handlers no longer block new connections.
        Each handler gets an isolated variable scope (as with coroutines).
        Combine with /max to bound the run, /timeout to stop after an idle
        period, or run it inside a coroutine for background use and cancellation
        (see CANCELLATION below). -4/-6/--dual/--keep-mapped all apply.

Cancellation

A /mthread server normally blocks until /max is reached. To run one in the
background and stop it on demand, wrap it in a procedure, start it with
corunproc, and stop it with cocancel:

    proc server_proc()
        tcpserver 8080 my_handler /mthread
    endproc
    corunproc server_proc          # returns a coroutine id
    ...
    cocancel <coid>                # or: cocancel /all

cocancel shuts the listener down cleanly. Handlers written as a loop are
cancelled GRACEFULLY: cshw loops poll the cancellation flag, so the loop breaks
on its own and the handler can run its own cleanup (e.g. 'socket close'):

    proc my_handler(sock)
        while 1
            socket recv $sock /timeout:500
            # ... handle $result ...
        end
        socket close $sock          # runs cleanly on cancel
    endproc

A handler parked in a plain blocking 'socket recv' (no /timeout, no loop) can't
notice cancellation, so the server force-closes its socket to wake it; that
recv then returns an error. Prefer the loop + /timeout shape above for clean
cancellation.

Handler Procedure

The handler procedure receives the client socket ID as its first argument.
The procedure is responsible for:
  - Reading from the socket (socket recv)
  - Writing to the socket (socket send)
  - Closing the socket when done (socket close)

Example handler:
    proc echo_handler(sock)
        socket recv $sock
        socket send $sock $result
        socket close $sock
    endproc

Examples

    # Echo server - returns whatever client sends
    proc echo_handler(sock)
        socket recv $sock
        socket send $sock $result
        socket close $sock
    endproc
    tcpserver 8080 echo_handler

    # HTTP server example
    proc http_handler(sock)
        socket recv $sock
        socket send $sock "HTTP/1.1 200 OK\r\nContent-Length: 13\r\n\r\nHello, World!"
        socket close $sock
    endproc
    tcpserver 80 http_handler

    # Accept only 10 connections
    tcpserver 8080 handler /max:10

    # Accept one connection (useful for testing)
    tcpserver 8080 handler /once

    # Run server in background using coroutine
    corunproc tcpserver 8080 handler
    echo "Server started in background"

Notes

Running in Background: To run the server in the background, use corunproc: corunproc tcpserver 8080 myHandler The server will run in a separate coroutine while you continue working in the shell.

Port Reuse: The server sets SO_REUSEADDR to allow quick restarts without waiting for TIME_WAIT to expire.

Exit status

0       Success (server exited normally)
>0      Error (bind failed, listen failed, etc.)

See also

tcpclient, socket, corunproc

tee back to top ↑

read from stdin and write to stdout and files

Synopsis

    command | tee FILE
    command | tee FILE1 FILE2...
    command | tee [options] FILE

Description

Reads from standard input and writes to both standard output AND one or more files. Like a "T" pipe fitting that splits the data flow.

Options

    FILE            File(s) to write to.

    -a, --append    Append to files instead of overwriting.
    -i, --ignore-interrupts
                    Ignore interrupt signals.

Examples

    dir | tee listing.txt
        Display dir output AND save to file.

    build.bat | tee build.log
        Show build output while logging.

    command | tee file1.txt file2.txt
        Write to multiple files.

    command | tee -a log.txt
        Append to existing log.

    longprocess | tee output.log | grep ERROR
        Log everything, display only errors.

    tar -cvf - src/ | tee backup.tar | md5sum
        Create archive and compute checksum simultaneously.

Exit status

0       Success
1       Write error

Notes

Non-Destructive Piping: Without tee, you choose either viewing OR saving: command > file # Saved but not displayed command # Displayed but not saved command | tee file # Both!

Multiple Outputs: tee can write to multiple files simultaneously: command | tee log1.txt log2.txt log3.txt

Pipeline Position: tee is typically in the middle of a pipeline: producer | tee file | consumer

Append Mode: Use -a to add to existing files rather than overwriting: status_check | tee -a daily.log

Real-Time Output: Output appears in real-time, not after completion.

See also

type, echo, grep

test back to top ↑

evaluate a conditional expression

Synopsis

    test <expression>
    [ <expression> ]

Description

Evaluate <expression> and report the result as the exit status: 0 when the expression is true, 1 when it is false, and 2 when the expression is malformed. test produces no output on success -- it exists to drive the && / || operators and $status checks.

`[` is an alias for test that requires a closing `]` as its final argument, so these two lines are equivalent:

test -f config.txt
[ -f config.txt ]

String tests: -z STR true if STR is empty -n STR true if STR is non-empty STR true if STR is non-empty (one-argument form) STR1 = STR2 true if the strings are equal (== is also accepted) STR1 != STR2 true if the strings differ

Integer tests (operands are compared numerically): N1 -eq N2 equal N1 -ne N2 not equal N1 -lt N2 less than N1 -le N2 less or equal N1 -gt N2 greater than N1 -ge N2 greater or equal

File tests: -e PATH PATH exists -f PATH PATH exists and is a regular file -d PATH PATH exists and is a directory -s PATH PATH exists and is not empty -r PATH PATH is readable -w PATH PATH is writable -x PATH PATH is executable

Negation: ! EXPR true if EXPR is false

To combine conditions, use the shell's own && and || between separate test invocations rather than -a / -o.

Examples

    test -f settings.cshw && source settings.cshw

    [ -n "$name" ] && echo "hello, $name"

    test $count -gt 10
    if ($status != 0) echo "too many"

Exit status

0 if the expression is true, 1 if false, 2 if it is malformed.

See also

if, true, false

testsplash back to top ↑

[INTERNAL] exercise the splash dialog in a chosen mode

Synopsis

    testsplash [<mode> [<duration_ms>]]

Description

INTERNAL / DEV-ONLY command. Not part of the public cshw command surface. Exists so developers can exercise every mode of the modal splash dialog during development.

For scripted use, see the public `splash` command (modeless, script-friendly lifecycle).

Options

    Same mode set as `splash`. See `man splash` for the list.

Notes

The name is deliberately awkward to discourage scripting use. If you reach for this in a real script, you almost certainly want `splash` + `endsplash` instead.

See also

splash, endsplash

time back to top ↑

measure command execution time

Synopsis

    time COMMAND [ARGS...]

Description

Executes a command and reports the time taken to complete. Shows real (wall-clock) time, user CPU time, and system CPU time.

Options

    COMMAND         Command to execute and time.
    ARGS            Arguments for the command.

Examples

    time dir /s
        Time a recursive directory listing.

    time find . -name "*.cpp"
        Time a file search.

    time sort largefile.txt > sorted.txt
        Time a sort operation.

    time build.bat
        Time a build script.

Exit status

Returns the exit code of the timed command.

Notes

Output Format: real 0m1.234s # Wall-clock time user 0m0.567s # CPU time in user mode sys 0m0.123s # CPU time in kernel mode

Real vs CPU Time: - Real: Actual elapsed time (includes I/O waits) - User: CPU time executing your code - Sys: CPU time in system calls

Performance Analysis: - High real, low CPU: I/O bound (waiting for disk/network) - High CPU, matches real: CPU bound (computation)

Multicore: User+sys can exceed real if multiple cores are used.

Precision: Timing precision depends on Windows timer resolution, typically around 15.6ms on desktop Windows.

Scripts: Useful for identifying slow operations in scripts or comparing different approaches.

See also

timeout, sleep, suspend

timeout back to top ↑

run command with time limit

Synopsis

    timeout DURATION COMMAND [ARGS...]
    timeout [options] DURATION COMMAND

Description

Runs a command and kills it if it doesn't complete within the specified time limit. Useful for commands that might hang or take too long.

Options

    DURATION        Time limit (seconds, or with suffix: s/m/h).
    COMMAND         Command to run.
    ARGS            Arguments for the command.

    -s SIGNAL       Signal to send on timeout (default: KILL).
    -k DURATION     Kill with SIGKILL after DURATION if still running.
    --preserve-status
                    Exit with command's status even on timeout.

Examples

    timeout 30 ping server.com
        Run ping for max 30 seconds.

    timeout 5m build.bat
        Allow 5 minutes for build.

    timeout 1h longprocess.exe
        1 hour limit.

    timeout 10 curl https://slow-server.com/file
        Kill download if it takes over 10 seconds.

    timeout 60 script.bat || echo "Timed out!"
        Handle timeout case.

Exit status

124     Command timed out
125     timeout command failed
126     Command found but not executable
127     Command not found
Other   Command's exit status (if completed)

Notes

Time Units: 30 30 seconds 30s 30 seconds 5m 5 minutes 1h 1 hour

Graceful Termination: By default, timeout sends a termination request. Use -k to ensure the process is killed if it ignores the request.

Use Cases: - Network commands that might hang - Build processes with time limits - Automated testing with deadlines - CI/CD pipeline steps

Scripting: Check exit code 124 to detect timeouts: timeout 10 command if ($? == 124) echo "Command timed out" endif

See also

time, kill, watch

title back to top ↑

set or display the console window title

Synopsis

    title [text ...]

Description

Sets the console window title to the given text. With no arguments, prints the current title to stdout and stores it in $result.

When multiple positional arguments are supplied, they are joined with spaces before being applied.

Examples

    title
        Print the current title.

    title "Build server"
        Set the title to "Build server".

    title cshw -- backup running
        Sets title to "cshw -- backup running" (positional join).

Exit status

0       Always.

See also

prompt, say

tokenize back to top ↑

display parsed tokens from input

Synopsis

    tokenize LINE
    tokenize "COMMAND WITH ARGS"

Description

Parses a command line and displays the tokens identified by the lexer. Useful for debugging command parsing, understanding how the shell interprets input, and developing shell scripts.

Options

    LINE            Text to tokenize.

Examples

    tokenize "echo hello world"
        # Token 0: Identifier "echo"
        # Token 1: Identifier "hello"
        # Token 2: Identifier "world"

    tokenize "set x=42"
        # Token 0: Identifier "set"
        # Token 1: Identifier "x"
        # Token 2: Operator "="
        # Token 3: Number "42"

    tokenize 'grep -i "pattern" file.txt'
        # Shows how quotes and switches are parsed

    tokenize "dir /s /b *.txt"
        # Token 0: Identifier "dir"
        # Token 1: Switch "/s"
        # Token 2: Switch "/b"
        # Token 3: Identifier "*.txt"

Exit status

0       Success

Notes

Token Types: - Identifier: Commands, filenames, arguments - String: Quoted text - Number: Numeric values - Operator: =, |, <, >, etc. - Switch: /x or -x style options - Variable: $name references

Debugging: tokenize helps understand: - How quotes are handled - Where words are split - How special characters are interpreted

Parser Development: Essential tool when developing or debugging shell scripts that depend on specific parsing behavior.

See also

echo, set

touch back to top ↑

change file timestamps or create empty files

Synopsis

    touch FILE...
    touch [options] FILE...

Description

Updates the access and modification times of files to the current time. If a file doesn't exist, touch creates an empty file with that name.

touch is commonly used to create empty files or to update timestamps for build systems that depend on file modification times.

Options

    FILE            File(s) to touch.

    -a              Change only the access time.
    -m              Change only the modification time.
                    With neither, both are set, as GNU touch does.
    -c, --no-create Do not create files that do not exist.
    -t TIMESTAMP    Use this time instead of the current time.
                    Format: [[CC]YY]MMDDhhmm[.ss]
                    A two-digit year 69-99 means 1969-1999; 00-68 means
                    2000-2068. With no year at all, the current year.
    -d, --date=STR  Use this time instead of the current time.
                    Format: "YYYY-MM-DD [HH:MM[:SS]]". This is not GNU's
                    full free-form date parser -- a string it cannot read
                    is refused, never silently treated as "now".
    -r, --reference=FILE
                    Use FILE's modification time.

Examples

    touch newfile.txt
        Create empty file or update existing file's timestamp.

    touch file1.txt file2.txt file3.txt
        Touch multiple files.

    touch -c maybeexists.txt
        Update timestamp only if file exists.

    touch -m important.dat
        Update only modification time.

    touch *.cpp
        Update timestamps on all C++ source files.

    touch -t 202601151200 dated.txt
        Set the timestamp to 15 January 2026, 12:00 local time.

    touch -d "2026-01-15 12:00" dated.txt
        The same, spelled readably.

    touch -r template.txt copy.txt
        Give copy.txt the same modification time as template.txt.

Exit status

0       Success
1       Cannot create file (permission denied)
2       Invalid arguments

Notes

Creating Files: touch is the standard way to create empty files in a shell. It's cleaner than "echo. > file" or similar.

Build Systems: touch is useful for forcing rebuilds in make-based systems by updating source file timestamps.

Timestamps: Windows files have creation, modification and access times. touch sets the modification and access times; the creation time is left alone.

Daylight saving: A timestamp given to -t or -d is local wall-clock time, converted with the DST rule in force ON THAT DATE rather than the one in force today. Setting a January time during the summer therefore stores January's offset, and reading it back with `stat` or `dir` returns the time that was asked for. Both directions used the current bias before, so half the year every timestamp from the other half was an hour out.

Time options used to be inert: -t was accepted and ignored, so `touch -t 202601151200 f` stamped f with the current time and returned 0 -- a script building a file with a known mtime silently got today instead.

See also

stat, dir, type

tr back to top ↑

translate or delete characters

Synopsis

    tr SET1 SET2
    tr -d SET1
    command | tr SET1 SET2

Description

Translates, squeezes, or deletes characters from standard input, writing to standard output. Useful for character substitution and cleanup.

Options

    SET1            Source character set.
    SET2            Replacement character set.

    -d, --delete    Delete characters in SET1 (no replacement).
    -s, --squeeze   Replace repeated characters with single occurrence.
    -c, --complement
                    Use complement of SET1.

    Character classes:
    [:alnum:]       Letters and digits
    [:alpha:]       Letters
    [:digit:]       Digits
    [:lower:]       Lowercase letters
    [:upper:]       Uppercase letters
    [:space:]       Whitespace
    [:punct:]       Punctuation

Examples

    echo "hello" | tr a-z A-Z
        Convert to uppercase: HELLO

    echo "HELLO" | tr A-Z a-z
        Convert to lowercase: hello

    echo "hello   world" | tr -s ' '
        Squeeze spaces: "hello world"

    echo "abc123" | tr -d '0-9'
        Delete digits: abc

    echo "hello" | tr 'aeiou' '12345'
        Replace vowels: h2ll4

    type file.txt | tr '\r\n' '\n'
        Convert Windows to Unix line endings.

    echo "a,b,c" | tr ',' '\n'
        Replace commas with newlines.

    echo "hello world" | tr -d ' '
        Remove all spaces: helloworld

    type file.txt | tr -d '\r'
        Remove carriage returns.

    echo "hello" | tr -c 'aeiou' '_'
        Replace non-vowels: _e__o

Exit status

0       Success
1       Error

Notes

Character Ranges: - a-z: Lowercase letters - A-Z: Uppercase letters - 0-9: Digits

Special Characters: - \n: Newline - \r: Carriage return - \t: Tab - \\: Backslash

One-to-One Mapping: Characters in SET1 map to corresponding positions in SET2. If SET2 is shorter, its last character is repeated.

Common Uses: - Case conversion - Removing unwanted characters - Line ending conversion - Character substitution

See also

cut, sed, grep

tree back to top ↑

display a directory structure graphically

Synopsis

    tree [PATH] [/f] [/a]

Description

Draws the directory structure below PATH, one line per entry, with the branch characters that show which levels are still open. With no PATH, draws the current directory.

Directories are listed alphabetically and case-insensitively, which is the order Windows itself presents them in.

Options

    /f          Include files as well as directories. Files are listed
                before subdirectories at each level, as cmd's tree does.
    /a          Draw with ASCII (+--- \--- |) instead of the line-drawing
                characters. Use it when the output is heading somewhere
                that cannot render them -- a log file read on another
                machine, or a terminal in a single-byte code page.

Examples

    tree
        The current directory, directories only.

    tree /f
        ...including files.

    tree C:\Projects\site /f /a
        A named directory, files included, in plain ASCII.

    tree > structure.txt
        Capture it. Consider /a as well, since a file has no font.

Exit status

0       The tree was drawn
1       PATH does not exist or is not a directory

Notes

A reparse point -- a junction or a symbolic link to a directory -- is listed but NOT descended. A junction pointing at one of its own ancestors would otherwise turn the listing into a walk with no end, and one pointing across the disk would silently include a tree that is not below PATH at all.

Paths are opened in extended-length form, so a tree deeper than MAX_PATH is drawn completely rather than stopping partway down without saying so.

See also

dir, ls, find, du, vol

true back to top ↑

succeed or fail with no side effects

Synopsis

    true
    false
    nop

Description

Three minimal commands that perform no work and only affect $status:

true    Sets $status to 0 (success).
false   Sets $status to 1 (failure).
nop     Identical to true. A no-op placeholder; succeeds.

`nop` is dispatcher-aliased to `true` and shares the same handler. Comment lines starting with `#` are discarded by the lexer before dispatch, so they neither run nor touch $status.

Useful in shell constructs that require a command but where you want a guaranteed success/failure, as a placeholder in empty branches, or to deliberately seed $status before a conditional.

Examples

    true
        Succeed. $status = 0.

    false
        Fail. $status = 1.

    nop
        Same as true. Useful as a placeholder.

    if ($condition)
        nop         # explicit no-op in the empty branch
    else
        # ...
    endif

    proc always_fail
        false
    endproc

Exit status

true, nop       0       Always.
false           1       Always.

Notes

true vs nop: Functionally identical -- both succeed without side effects. true is the conventional Unix name; nop is the legacy cshw spelling. Both remain registered and point at the same handler.

Comments: The `#` prefix is recognized by the lexer (lexer.cpp:111) and the rest of the line is consumed without emitting any token. Inline comments (`echo hi # trailing`) work the same way. `#` never reaches the dispatcher.

See also

exit

tsrvd back to top ↑

launch and supervise tsrvd server worker processes

Synopsis

    tsrvd start <port> [handler] [/stream] [/dll:<path>] [/workers:N] [/norestart]
    tsrvd status <id>
    tsrvd stop <id>
    tsrvd list
    tsrvd recv|send|close <conn>          (only inside a /stream handler)

Description

Runs the multithreaded TCP server in a SEPARATE process (tsrvd.exe), with cshw as the master: cshw launches the worker, supervises it over a control pipe, and can query its status or stop it. Because the worker is its own process, a crash in the server's network handling cannot take down the shell.

tsrvd.exe is found next to cshw.exe. Each connection the worker accepts is RELAYED to the cshw `handler` proc over a per-connection pipe: the handler receives the request as its argument and its return value is sent back as the response (line-oriented request/response in this version). cshw never touches the socket -- the worker owns it. See also: tcpserver, which runs an in-process server when you want handlers to share the shell's live state directly.

Subcommands

    start <port> [handler] [/workers:N] [/norestart]
        Launch a worker listening on <port>, relaying each connection to the cshw
        proc <handler> (omit it for a no-op server). Blocks until the worker is up.
        Sets $result to the new daemon id. /workers caps the worker thread pool.
        By default a worker that dies unexpectedly is auto-restarted (with
        backoff); /norestart disables that.

        Example handler (echoes the request back):
            proc my_handler(req)
                return "got: $req"
            endproc
            tsrvd start 8080 my_handler

    status <id>
        Query the worker and print its STAT line:
            STAT <accepted> <active> <running>
        (total connections accepted, currently active, and 1 if listening).
        Also sets $result to that line.

    stop <id>
        Ask the worker to stop; if it overstays it is terminated. Removes it
        from the list.

    list
        Show all launched workers: id, port, pid, state (running/dead/failed),
        restart count (RST), and the last STAT seen.

Streaming

By default the handler is request/response: handler(request) -> return response,
one exchange per connection. With /stream the handler instead DRIVES the
connection -- it is called as handler(conn) and uses proxied socket ops over the
per-connection pipe for a multi-message conversation:

    proc chat(conn)
        while 1
            tsrvd recv $conn          # sets $result; $? != 0 at end of stream
            if $? != 0
                break
            endif
            tsrvd send $conn "echo:$result"
        end
        tsrvd close $conn
    endproc
    tsrvd start 8087 chat /stream

recv/send/close operate on the <conn> handle the handler is given; they are only
meaningful inside a /stream handler. The socket still lives in the tsrvd worker;
cshw only exchanges request/response bytes over the pipe.

Plugins

Instead of a cshw handler, a worker can load a native handler DLL that owns the
protocol end to end:

    tsrvd start 8080 /dll:http.dll

cshw never sees the connections in this mode -- it only launches and supervises
the worker (status / stop / auto-restart still apply). The DLL implements the
stable C ABI in tsrvd_plugin.h: TsrvdAbiVersion, TsrvdInit, TsrvdOnConnection
(called per connection on a worker thread), TsrvdShutdown. tsrvd hands each
connection a small vtable (recv/send/close/peer/stopping); the plugin links
nothing of tsrvd. Reference plugins: echo.dll (byte echo), http.dll (HTTP/1.1 +
HTTP/2 static-file + CGI web server, HTTPS via TLS; HTTP/3 is the separate
quicsrv worker), smtp.dll (full ESMTP server: AUTH PLAIN/LOGIN, STARTTLS, maildir/mbox
delivery -- see smtp.conf.example), ftp.dll (FTP server: login/anonymous,
passive+active, browse/download and optional writes, sandboxed to a root -- see
ftp.conf.example), and pop3.dll (POP3 server with STLS that serves the smtp
per-user spool, so clients retrieve received mail -- see pop3.conf.example). The
DLL is found next to tsrvd.exe, or give a full path.
Plugin config goes through /dllcfg:<file>, e.g.

    tsrvd start 25 /dll:smtp.dll /dllcfg:smtp.conf

cshw's `checkmail` builtin / the $mail prompt check can then watch smtp.dll's
per-user spool and announce "You have new mail for user: <name>".

.AUTO-RESTART
A worker that exits unexpectedly is relaunched automatically, with increasing
backoff. If it crash-loops (too many restarts in a short window) it is marked
'failed' and left alone (visible in `tsrvd list`); `tsrvd stop <id>` clears it.
Use /norestart on `start` to opt out.

Examples

    # Launch an isolated server on 8080, check it, then stop it
    tsrvd start 8080
    set sid $result
    tsrvd status $sid
    tsrvd stop $sid

    # See everything that's running
    tsrvd list

Notes

If cshw exits, its control pipes close and each worker detects the master is gone and stops itself -- so workers are not orphaned.

Exit status

0       Success
>0      Error (worker not found, failed to launch, etc.)

See also

tcpserver, socket, corunproc

type back to top ↑

display file contents

Synopsis

    type FILE...
    type FILE | command

Description

Displays the contents of one or more files to standard output. Similar to the UNIX 'cat' command, type is used for viewing file contents, concatenating files, and feeding file contents into pipelines.

When multiple files are specified, their contents are displayed sequentially, effectively concatenating them.

Options

    FILE            One or more files to display.

Examples

    type readme.txt
        Display contents of readme.txt.

    type file1.txt file2.txt
        Display contents of both files sequentially.

    type log.txt | grep error
        Pipe file contents to grep for filtering.

    type config.ini | head 20
        Show first 20 lines of a config file.

    type *.txt
        Display contents of all text files.

    type data.csv | wc -l
        Count lines in a CSV file.

    type script.csh | grep "proc "
        Find procedure definitions in a script.

Exit status

0       Success
1       File not found
2       Access denied or read error

Notes

Binary Files: Type is designed for text files. Displaying binary files will produce garbled output and may affect your terminal.

Large Files: For large files, consider using 'head' or 'tail' to view portions, or pipe through 'grep' to find specific content.

Encoding: CSHW's type command handles UTF-8 and UTF-16 encoded files automatically. For other encodings, output may appear incorrect.

Piping: Type is frequently used as the start of a pipeline to feed file contents into other commands like grep, sort, wc, etc.

See also

head, tail, grep, wc, copy

umask back to top ↑

set file creation mode mask

Synopsis

    umask
    umask MASK

Description

Displays or sets the file creation mode mask. The umask value is subtracted from the default permissions when creating new files.

On Windows, umask has limited effect since Windows uses ACLs rather than UNIX-style permissions.

Options

    MASK            Octal permission mask (e.g., 022, 077).

Examples

    umask
        Display current umask value.

    umask 022
        Common umask: files 644, directories 755.

    umask 077
        Restrictive: only owner can access new files.

    umask 002
        Group-friendly: files 664, directories 775.

Exit status

0       Success

Notes

How umask Works: Default permissions minus umask equals actual permissions. File default: 666 (rw-rw-rw-) umask: 022 Result: 644 (rw-r--r--)

Directory default: 777 (rwxrwxrwx)
umask:             022
Result:            755 (rwxr-xr-x)

Common Values: 022 Standard user (owner full, others read) 077 Private (owner only) 002 Collaborative (group full) 000 No mask (full permissions)

Windows Limitations: Windows doesn't use UNIX permissions natively. umask affects: - Files created by POSIX-compatible operations - Cygwin/MSYS interoperability - Cross-platform script behavior

Persistence: umask affects only the current shell. Set in startup scripts for persistence.

See also

chmod, chown, touch

unalias back to top ↑

remove command aliases

Synopsis

    unalias NAME
    unalias NAME...
    unalias -a

Description

Removes one or more previously defined command aliases. After removal, the alias name will no longer expand to its defined command.

Options

    NAME            Alias name(s) to remove.
    -a, --all       Remove all defined aliases.

Examples

    unalias ll
        Remove the 'll' alias.

    unalias ll la ls
        Remove multiple aliases.

    unalias -a
        Remove all aliases.

    alias g=grep
    g pattern file.txt    # Works
    unalias g
    g pattern file.txt    # Error: g not found

Exit status

0       Success
1       Alias not found

Notes

Non-existent Aliases: Removing an alias that doesn't exist may produce a warning but is not a fatal error.

Persistence: Like aliases, unalias changes only affect the current session. To permanently remove an alias, edit your startup script.

Restoring Commands: If you aliased over a built-in command, unalias restores access to the original command.

See also

alias, set, unset

uname back to top ↑

print system information

Synopsis

    uname
    uname [options]

Description

Displays system information including operating system name, version, machine architecture, and more. Provides UNIX-compatible system identification on Windows.

Options

    -a, --all       Print all information.
    -s, --kernel-name
                    Print operating system name.
    -n, --nodename  Print network node hostname.
    -r, --kernel-release
                    Print kernel/OS release.
    -v, --kernel-version
                    Print kernel/OS version.
    -m, --machine   Print machine hardware name (architecture).
    -p, --processor Print processor type.
    -o, --operating-system
                    Print operating system name.

Examples

    uname
        Print OS name (Windows_NT).

    uname -a
        Print all system information.

    uname -m
        Print architecture (x86_64 or ARM64).

    uname -r
        Print OS version/build.

    uname -n
        Print computer name.

Exit status

0       Success

Notes

Output Format: With -a, output is: OS nodename release version machine processor

Windows Values: - OS: Windows_NT - Machine: x86_64 (AMD64) or ARM64 - Release: Windows version (e.g., 10.0.19045)

Cross-Platform Scripts: uname allows scripts to detect the operating system: if ($(uname -s) == "Windows_NT") echo "Running on Windows" endif

Comparison: - uname: UNIX-style system info - winver: Windows-specific version details - version: CSHW shell version

See also

winver, version, whoami

unbindevent back to top ↑

remove a window event binding

Synopsis

    unbindevent <hwnd> <kind> [<args>]

Description

Removes a binding previously installed by `bindevent`. The kind and per-kind args identify which binding to remove (same key shape as `bindevent`). Removing a binding that doesn't exist is a clean no-op.

Options

    <hwnd>      Target HWND. (IsWindow() is NOT required here -- removing
                a binding from a destroyed window is allowed.)
    <kind>      Same kinds as `bindevent`. Per-kind args identify
                command/notify/timer/keydown bindings; close/destroy/
                lbutton/size take no extras.

Examples

    unbindevent $w command 100
    unbindevent $w close
    unbindevent $w keydown 27         # remove the Esc-key handler

Exit status

0       Success (including the no-op case).
1       Bad HWND syntax, unknown kind, or missing args.

See also

bindevent, createwindow

uncomplete back to top ↑

remove tab completion rules

Synopsis

    uncomplete COMMAND
    uncomplete COMMAND...

Description

Removes custom tab completion rules for commands, reverting to default file completion behavior.

Options

    COMMAND         Command(s) to remove completion rules for.

Examples

    uncomplete cd
        Remove custom cd completion.

    uncomplete git svn hg
        Remove completion for multiple commands.

    complete cd d
    # Tab after cd shows only directories
    uncomplete cd
    # Tab after cd now shows files too

Exit status

0       Success
1       No rule defined for command

Notes

Effect: After uncomplete, the command uses default file completion.

Use Cases: - Reset unwanted completion behavior - Debug completion issues - Temporarily disable custom completion

See also

complete, alias

unfileblob back to top ↑

decode a fileblob back into a file

Synopsis

    unfileblob [blob] [outfile]

Description

unfileblob reverses fileblob: it takes a CSHWBLOB1 text blob and writes the decoded bytes back out as a file.

The blob may be supplied as an argument -- typically a shell variable holding one -- or piped in on standard input. If <outfile> is given it is used as the destination; otherwise the original filename embedded in the blob is used.

Examples

    unfileblob "$logo" icon.png
        Decode a blob held in a variable to a named file.

    unfileblob < icon.blob
        Decode a saved blob file, restoring the original filename.

Exit status

0 on success; non-zero if the input is not a valid fileblob or the output file cannot be written.

See also

fileblob, base64

unhash back to top ↑

remove command from hash table

Synopsis

    unhash COMMAND
    unhash COMMAND...

Description

Removes one or more commands from the hash table cache. Next time the command is run, the shell will search PATH to find it.

Options

    COMMAND         Command name(s) to remove from cache.

Examples

    unhash python
        Remove python from cache.

    unhash git python node
        Remove multiple commands.

    # After replacing a program with new version:
    unhash myprogram
    myprogram   # Now finds the new version

Exit status

0       Success
1       Command not in hash table

Notes

Use Cases: - Force shell to find updated program location - Clear cache for specific command - Debug command resolution issues

vs rehash: - unhash: Removes specific entries - rehash: Rebuilds entire table

After unhash, the command is looked up in PATH on next execution and potentially re-added to the hash.

See also

rehash, hashstat, which

uniq back to top ↑

report or filter out repeated lines

Synopsis

    uniq [options] [FILE]
    sort FILE | uniq

Description

Filters adjacent matching lines from input. Typically used after sort to remove or count duplicate lines.

Note: uniq only removes ADJACENT duplicates. Sort input first to remove all duplicates, or use 'sort -u'.

Options

    FILE            File to process (default: stdin).

    -c, --count     Prefix lines with occurrence count.
    -d, --repeated  Only print duplicate lines.
    -u, --unique    Only print unique lines (appears once).
    -i, --ignore-case
                    Ignore case when comparing.

Examples

    sort names.txt | uniq
        Remove all duplicate lines.

    uniq -c sorted.txt
        Count occurrences of each line.

    sort data.txt | uniq -d
        Show only duplicated lines.

    sort data.txt | uniq -u
        Show only lines that appear once.

    dir /b | sort | uniq
        List unique filenames.

    type log.txt | grep ERROR | sort | uniq -c
        Count unique error messages.

Exit status

0       Success
1       Error

Notes

Important: Sort First! uniq only compares adjacent lines. To remove all duplicates: sort file.txt | uniq

Or use: sort -u file.txt

Counting: The -c option is useful for frequency analysis: cat access.log | cut -d' ' -f1 | sort | uniq -c | sort -rn

See also

sort, wc, grep

unlimit back to top ↑

report that resource limits cannot be removed

Synopsis

    unlimit
    unlimit RESOURCE

Description

Accepted for tcsh compatibility. IT REMOVES NOTHING, because there is nothing to remove: Windows has no per-process rlimit that a shell can raise or drop. unlimit prints where the figures `limit` reports actually come from and exits 0.

Earlier versions of this page described raising soft limits toward hard limits and a permission-denied exit code for the attempts that failed. No such mechanism exists here, and no attempt is made.

Options

    RESOURCE        Accepted and ignored. See `limit` for the list of
                    resources that can be reported.

Examples

    unlimit
        Print the explanation.

    unlimit filesize
        The same. The resource name changes nothing.

Exit status

0       Always. Nothing was attempted, so nothing can fail.

Notes

Why: UNIX rlimits are per-process kernel state a program can adjust for itself. The Windows equivalent is the Job Object, which is applied to a process from outside and governs the whole job. A shell cannot lift its own ceiling, so `unlimit` has nothing to act on.

What to use instead: Nothing in cshw constrains a child process by default, so there is generally nothing in the way. If a program needs MORE than the system allows -- more handles, a bigger stack -- that is set in the program's own PE header or manifest, not by the shell that launches it.

Reporting: `limit` with no argument prints every resource, this process's usage, and system memory. That is the useful half of this pair.

See also

limit, nice, time

unregistercmdlib back to top ↑

unregister command library (unload plugin DLL)

Synopsis

    unregistercmdlib PATH|NAME|PREFIX
    unregistercmdlib /all
    urcl PATH|NAME|PREFIX
    urcl /all

Description

Alias for urcl. See 'man urcl' for full documentation.

See also

urcl, rcl, cmdliblist

unset back to top ↑

remove shell variables

Synopsis

    unset NAME
    unset NAME...

Description

Removes one or more shell variables from the current environment. After unsetting, the variable is no longer defined and references to it will return empty values.

Options

    NAME            One or more variable names to remove.

Examples

    unset count
        Remove the variable 'count'.

    unset var1 var2 var3
        Remove multiple variables.

    set temp="temporary"
    echo $temp
    unset temp
    echo $temp
        # Second echo outputs nothing

Exit status

0       Success
1       Variable not found (may still succeed)

Notes

Non-existent Variables: Unsetting a variable that doesn't exist is not an error.

Environment Variables: unset removes shell variables. To remove environment variables, use 'unsetenv' instead.

Special Variables: Some special variables ($?, $:, $$) cannot be unset as they are managed by the shell.

Scope: unset only affects variables in the current shell scope. Variables in parent or child processes are not affected.

See also

set, unsetenv, vartype

unsetenv back to top ↑

remove environment variable

Synopsis

    unsetenv NAME
    unsetenv NAME...

Description

Removes one or more environment variables from the current process environment. Child processes will not inherit the removed variables.

Options

    NAME            Environment variable name(s) to remove.

Examples

    unsetenv DEBUG
        Remove DEBUG variable.

    unsetenv TEMP_VAR MY_CONFIG
        Remove multiple variables.

    setenv TEST_VAR "hello"
    echo %TEST_VAR%
    unsetenv TEST_VAR
    echo %TEST_VAR%
        # Second echo shows empty

Exit status

0       Success
1       Error

Notes

System Variables: Some system variables (PATH, SYSTEMROOT, etc.) should not be unset as they may affect system operation.

Scope: unsetenv only affects the current process and its future children. It does not affect: - The parent process - Other running programs - System environment (permanent settings)

Verification: Use 'env' or 'printenv' to verify the variable was removed.

See also

setenv, unset, env, printenv

unshadow back to top ↑

restore a built-in hidden by shadow

Synopsis

    unshadow COMMAND ...
    unshadow -a

Description

Puts a built-in back into command lookup after `shadow` took it out. The command was never destroyed, only set aside, so this always succeeds for anything `shadow` hid.

Options

    COMMAND         A shadowed built-in to restore. Several may be
                    named at once.
    -a, --all       Restore every shadowed built-in.

Examples

    unshadow tree
        Give `tree` back to the built-in.

    unshadow -a
        Restore everything. Worth knowing when a startup script has
        shadowed more than its author remembers; `shadow` with no
        arguments lists what that is.

Exit status

0       Every named command was restored.
1       At least one name was not shadowed to begin with.

Notes

Only what shadow hid: A plugin loaded with `rcl` also displaces an intrinsic of the same name, and that one belongs to `urcl`. unshadow will not restore it, and says the name is not shadowed -- the two mechanisms share a store, so keeping them apart is what stops `unshadow` from pulling a command out from under a loaded plugin.

See also

shadow, which, where, urcl

unzip back to top ↑

extract or list a .zip archive

Synopsis

    unzip [/l] [/d:<dir>] [/p[:<password>]] <archive.zip>

Description

Extract a .zip archive, or list its contents without extracting. Supports password-encrypted archives via /p.

Options

    /l, /list, --list
        List archive contents instead of extracting. Prints entry
        names, sizes, and last-modified timestamps.

    /d:<dir>, --dest:<dir>
        Extract into <dir> rather than the current directory. The
        directory is created if it doesn't exist.

    /p[:<password>]
        Password for encrypted archives. Bare /p prompts on the
        console; /p:<value> uses the literal password.

    <archive.zip>
        Archive to extract or list.

Examples

    unzip backup.zip
        Extract everything into the current directory.

    unzip /l backup.zip
        List archive contents.

    unzip /d:out backup.zip
        Extract into out/.

    unzip /p:s3cret secret.zip
        Extract a password-protected archive.

Exit status

0       Extraction or listing succeeded.
1       Bad arguments, archive not found, wrong password, or I/O error.

See also

zip, tar

uptime back to top ↑

show how long system has been running

Synopsis

    uptime

Description

Displays the current time, how long the system has been running, and system load information.

Examples

    uptime
        Display system uptime.

Exit status

0       Success

Notes

Output includes: - Current time - Time since last boot (days, hours, minutes) - Number of logged-in users (if available)

Windows Uptime: On Windows, uptime is calculated from the system boot time. This can also be viewed in Task Manager's Performance tab.

Long Uptimes: Servers often have uptimes measured in weeks or months. Desktops typically restart more frequently for updates.

See also

uname, processlist, df

urcl back to top ↑

unregister command library (unload plugin DLL)

Synopsis

    urcl PATH|NAME|PREFIX
    urcl /all
    unregistercmdlib PATH|NAME|PREFIX
    unregistercmdlib /all

Description

Unloads a previously registered command library and removes all its commands from the shell.

The library can be identified by its DLL path, library name, or namespace prefix.

If the library had shadowed any intrinsic commands, those built-in commands are restored when the library is unloaded.

The plugin's UnregisterCommandLibrary function is called (if exported) to allow cleanup before the DLL is freed from memory.

Options

    PATH|NAME|PREFIX    Identify library by DLL path, name, or prefix.
    /all                Unload all command libraries.
    /a                  Short form of /all.

Examples

    urcl mylib
        Unload library by its prefix or name.

    urcl C:\Plugins\mylib.dll
        Unload library by its DLL path.

    urcl /all
        Unload all loaded command libraries.

Exit status

0       Success
1       Library not found

Notes

Cleanup: Before unloading, the shell calls UnregisterCommandLibrary if the DLL exports it. Use this to release resources, close handles, etc.

Restoration: If the library had shadowed built-in commands (e.g., provided its own "echo" command), the original intrinsic commands are automatically restored when the library is unloaded.

Order: When unloading all libraries with /all, they are unloaded in arbitrary order. Design plugins to not depend on unload order.

See also

rcl, cmdliblist

vartype back to top ↑

display variable type

Synopsis

    vartype NAME
    vartype $NAME

Description

Displays the data type of a shell variable. CSHW automatically tracks variable types based on assigned values, supporting strings, integers, and floating-point numbers.

Options

    NAME            Variable name to examine (with or without $).

Examples

    set count=42
    vartype count
        # Output: integer

    set name="John"
    vartype name
        # Output: string

    set pi=3.14159
    vartype pi
        # Output: float

    set hex=0xFF
    vartype hex
        # Output: integer

Exit status

0       Success
1       Variable not found

Notes

Type Inference: CSHW infers types automatically: - Integer: whole numbers (42, -17, 0xFF, 0b1010) - Float: numbers with decimals (3.14) or exponents (1e-3) - String: everything else

Type Conversion: Variables can change type when reassigned: set x=42 # integer set x="hello" # now string

Type in Expressions: Type matters in expressions. String comparisons use lexicographic order, numeric comparisons use numeric order.

See also

set, unset, echo

ver back to top ↑

display shell version (alias for version)

Synopsis

    ver

Options

    -s, --short    Print just the version number, for scripts.

Description

`ver` is identical to `version`. See `man version` for details.

See also

version, about, winver

version back to top ↑

display shell version

Synopsis

    version
    ver

Description

Aliases: ver

Displays the CSHW shell version number and build information.

Examples

    version
        Display shell version.

    ver
        Short form (alias for version).

Exit status

0       Success (always)

Notes

The version command shows the CSHW version. For Windows version information, use 'winver' instead.

See also

winver, uname

vol back to top ↑

display a volume's label and serial number

Synopsis

    vol [DRIVE:]

Description

Prints the volume label and serial number of a drive, in the wording cmd.exe uses -- scripts that grep this output are the reason to match it rather than improve it.

With no argument, reports the volume holding the CURRENT DIRECTORY. That is resolved with GetVolumePathName rather than by slicing off the first two characters, so it is right on a mapped drive and on a directory mounted into another volume's namespace.

Options

    DRIVE:      Drive to report. A path works too: `vol .` and
                `vol C:\some\mount\point` both name the volume that
                actually holds them.

Examples

    vol
        The volume holding the current directory.

    vol D:
        A named drive.

    vol \\server\share
        A UNC path. There is no drive letter, so the share is named
        instead of printing a stray colon.

Exit status

0       The volume was read
1       No such drive, or its information could not be read

Notes

A volume with no label prints "has no label." rather than an empty name, which is what cmd.exe does and what a script testing for a label expects to see.

See also

df, du, dir, tree

wait back to top ↑

Wait for all running coroutines (alias for `cowait /all`).

No detailed man page yet — see the one-line summary above.

watch back to top ↑

execute command periodically

Synopsis

    watch COMMAND
    watch -n INTERVAL COMMAND
    watch [options] COMMAND

Description

Executes a command repeatedly at regular intervals, displaying the output. Useful for monitoring changes over time. Press Ctrl+C to stop.

Options

    COMMAND         Command to execute repeatedly.

    -n INTERVAL     Seconds between executions (default: 2).
    -d, --differences
                    Highlight differences between updates.
    -t, --no-title  Don't show header with time and command.
    -e, --errexit   Exit on command error.

Examples

    watch dir
        Monitor directory changes every 2 seconds.

    watch -n 5 processlist
        Show process list every 5 seconds.

    watch -n 10 df
        Monitor disk space every 10 seconds.

    watch -d "dir /b"
        Highlight file changes.

    watch -n 1 "type log.txt | tail -10"
        Monitor last 10 lines of log.

    watch "grep ERROR log.txt | wc -l"
        Count errors continuously.

Exit status

0       Exited normally (Ctrl+C)
1       Error running command
2       Invalid arguments

Notes

Display: watch clears the screen and shows fresh output each interval. The header shows current time and the command being run.

Quoted Commands: For commands with pipes or multiple arguments, use quotes: watch "ps | grep python"

Interval: Minimum interval is typically 0.1 seconds. Very short intervals can cause high CPU usage.

Use Cases: - Monitor log files for new entries - Watch process status changes - Track disk space - Observe build progress - Check network connectivity

Stopping: Press Ctrl+C to stop watching.

See also

time, timeout, tail

wc back to top ↑

word, line, character, and byte count

Synopsis

    wc [options] FILE...
    command | wc [options]

Description

Counts lines, words, characters, and bytes in files or standard input. By default, displays all counts. Options allow selecting specific counts.

Options

    FILE            One or more files to count.

    -l, --lines     Print only line counts.
    -w, --words     Print only word counts.
    -c, --bytes     Print only byte counts.
    -m, --chars     Print only character counts.

Examples

    wc file.txt
        Show lines, words, and bytes for file.txt.

    wc -l file.txt
        Count only lines.

    wc -w document.txt
        Count only words.

    wc *.txt
        Count for all text files (with totals).

    dir /b | wc -l
        Count number of files in directory.

    find . -name "*.cpp" | wc -l
        Count number of C++ files.

    type log.txt | grep error | wc -l
        Count error lines in log.

    wc -l -w report.txt
        Show both line and word counts.

Exit status

0       Success
1       File not found
2       Read error

Notes

Output Format: Default output shows: lines words bytes filename With multiple files, a total line is added.

Words: A "word" is defined as a sequence of non-whitespace characters separated by whitespace.

Characters vs Bytes: For ASCII text, -c and -m give the same result. For UTF-8 encoded files, -m counts Unicode characters while -c counts bytes.

Common Uses: - Count lines in a file: wc -l file.txt - Count files: dir /b | wc -l - Measure code: wc -l *.cpp *.h

See also

head, tail, type, grep

where back to top ↑

locate every place a command name resolves

Synopsis

    where NAME
    where /R DIR NAME

Description

Reports every place NAME resolves, in the order the dispatcher actually consults them: shell procedure, then alias, then built-in, then each directory of PATH. 'which' stops at the first answer; 'where' shows all of them, which is what makes it the tool for "why am I getting THAT one".

For the PATH search, NAME is tried bare and then with each of the executable extensions .exe, .com, .bat, .cmd and .ps1. The current directory is searched before PATH.

With /R, a directory tree is searched instead of PATH, using the same extension list.

Options

    NAME            Exact command or file name to locate. NOT a pattern --
                    see WILDCARDS below.
    /R DIR          Search the tree under DIR instead of PATH.
                    /r is accepted too.

Examples

    where notepad
        # C:\windows\system32\notepad.exe
        # C:\windows\notepad.exe

    where pwd
        # pwd: shell procedure
        # pwd: cshw built-in command
        Shows that a procedure is shadowing the built-in.

    where /R C:\Tools mytool.exe
        Search the C:\Tools tree for mytool.exe.

Exit status

0       At least one match found
1       No matches found

Notes

Wildcards: NOT supported. NAME is matched exactly (case-insensitively, plus the extension list) -- there is no globbing inside where. Earlier versions of this page advertised `where *.exe` and `where java*`; neither ever worked. Note also that the SHELL expands the pattern before where is invoked, so `where *.exe` usually fails with "No match." from the globber and where itself never runs at all.

Repeated results: where reports one hit per PATH entry, and does not deduplicate. If the same directory appears in PATH three times, its match is printed three times. That is faithful -- it is showing what PATH actually says. The same goes for entries differing only in case: C:\windows and C:\WINDOWS are two separate entries and produce two separate lines.

Which one runs: The first line is what would execute if you typed the name:

proc > alias > built-in > PATH

An alias beats a built-in, as it does in tcsh and bash -- that is what makes `alias ls 'ls -l'` do anything. A procedure beats both; csh has no functions so tcsh never had to rank them, and cshw puts its own on top.

The order here is not decoration. The whole promise of this command is that the first line is the winner and the rest are shadowed, so it has to match what the dispatcher does or it is worse than saying nothing.

/R and reparse points: The recursive walk does not follow junctions or symbolic links. A reparse point aimed at one of its own ancestors would otherwise make the walk re-enter the same subtree indefinitely -- and the standard example ships on every Windows install, since each user profile has AppData\Roaming\Application Data pointing straight back at AppData\Roaming. The consequence to know about: a file reachable only through a junction is not reported. Search the link's target directly.

/R and long paths: The walk is not limited to MAX_PATH (260 characters). It searches in the extended-length namespace internally, so files nested deeper than that are found and reported normally. The internal \\?\ prefix never appears in output.

This applies to the /R walk specifically. Other commands that take a path are still subject to the 260-character limit.

/R cost: /R is a full recursive enumeration with no index behind it. Pointing it at a large tree is genuinely slow: searching all of C:\Windows means walking roughly 700,000 entries and takes the better part of a minute. Point it at the narrowest directory that could hold what you are looking for.

See also

which, find, dir

which back to top ↑

locate a command

Synopsis

    which COMMAND
    which COMMAND...

Description

Displays the full path of the executable that would be run for each COMMAND. Searches through the PATH environment variable to find the first matching executable.

Options

    COMMAND         Command name(s) to locate.

Examples

    which notepad
        # C:\Windows\System32\notepad.exe

    which python
        # C:\Python311\python.exe

    which git
        # C:\Program Files\Git\cmd\git.exe

    which grep
        # (built-in) - for CSHW built-in commands

    which notepad python
        Locate multiple commands.

    which nonexistent
        # Command not found

Exit status

0       Command found
1       Command not found

Notes

Search Order: 1. Built-in shell commands 2. Aliases 3. PATH directories (left to right)

Executables: On Windows, which looks for files with executable extensions: .exe, .com, .bat, .cmd, .ps1

Built-in Commands: For built-in commands, which indicates "(built-in)" instead of a file path.

Multiple Matches: which shows only the first match, in the order the dispatcher resolves names:

proc > alias > built-in > PATH

Use 'where' to see all of them. An alias beats a built-in, so a name that is both is reported as the alias -- that is what actually runs.

Shadowed built-ins: A built-in hidden with `shadow` is NOT reported as a built-in, because it is no longer what runs. which reports whatever PATH turns up instead, with the reason appended:

which tree                  tree: cshw built-in command
shadow tree ; which tree    C:\Windows\System32\tree.com (shadowed intrinsic)

Case Sensitivity: Command names are case-insensitive on Windows.

See also

where, type, alias, shadow, unshadow

whoami back to top ↑

display current user name

Synopsis

    whoami
    whoami [options]

Description

Displays the user name of the current user. On Windows, shows the username in DOMAIN\username format.

Options

    /upn            Display the User Principal Name (user@domain).
    /fqdn           Display the fully qualified DN.
    /user           Display the account name and its SID.
    /groups         Display groups the user belongs to.
    /priv           Display user privileges.
    /all            Display all available information.

    /user, /upn and /fqdn each REPLACE the default DOMAIN\user line
    rather than adding to it, the same way Windows' own whoami.exe
    treats them. /groups, /priv and /all add to it.

Examples

    whoami
        Display current username.

    whoami /groups
        Show group memberships.

    whoami /priv
        Show user privileges.

    whoami /all
        Display comprehensive user information.

Exit status

0       Success
1       Error

Notes

Administrator Check: To check if running as Administrator, look for BUILTIN\Administrators in 'whoami /groups' output.

Domain vs Local: On domain-joined machines, shows the domain name. On standalone machines, the computer name.

/upn and /fqdn need a domain: Both names exist only for a domain account. On a workgroup machine whoami says so and exits 1, rather than printing the down-level DOMAIN\user name and letting it pass for a UPN -- which is what all three of these options used to do.

See also

env, uname

winapi back to top ↑

call a Win32 API by name with auto-resolution of its DLL

Synopsis

    winapi [-d] [-v] [-h] FUNCTION [ARGS...]

Description

Sugar layer over rundllproc. Looks FUNCTION up in cshw's built-in table of common Win32 APIs, resolves the hosting DLL (kernel32, user32, gdi32, advapi32, shell32, ole32, ws2_32, ...) and picks the W or A variant appropriate to cshw's wide-char default, then dispatches the existing rundllproc command.

Most callers never have to remember which DLL exports a function. For unusual cases (private DLL, ordinal lookup, non-standard signature) use rundllproc directly.

Options

    -d, --dump         Print the resolved <dll>::<name> and exit.
                       Useful for verifying which export will be called.
    -v, --verbose      Forwarded to rundllproc; prints handle and args.
    -h, --help         Show built-in help.
    FUNCTION           Win32 API name. Bare name picks the W variant
                       by default for W/A pairs; append A or W to force
                       a specific variant (MessageBoxA vs MessageBox).
    ARGS               Arguments forwarded verbatim to rundllproc.

Examples

    winapi GetTickCount
        kernel32::GetTickCount -- no arguments, no W/A variant.

    winapi Sleep 250
        kernel32::Sleep called with a 250 ms delay.

    winapi MessageBox 0 "hi" "cshw" 0
        Resolves to user32::MessageBoxW. The bare name picks W.

    winapi MessageBoxA 0 "hi" "cshw" 0
        Forces the ANSI variant.

    winapi -d CreateWindow
        Prints "user32.dll::CreateWindowW" without calling anything.

    winapi -v GetSystemDirectory
        Verbose call, shows DLL handle and arg marshalling.

Exit status

0       Success (the function returned; the value is in $?).
1       Function name not in table and no user override; or the
        underlying rundllproc call failed.
2       Syntax error (no function name, unknown option).

Notes

Extending the table: A user-level TSV at %APPDATA%\cshw\winapi.tsv adds or overrides entries: FunctionName<TAB>your.dll<TAB>None|W|A Lines beginning with '#' are comments. User entries win over built-ins, so this is also the way to remap a name to a different DLL.

Resolution order: 1. Exact name match in user TSV. 2. Exact name match in the baked-in table. 3. Strip a trailing W or A and retry (so CreateWindowA finds the CreateWindow entry and dispatches the literal name you typed). 4. Friendly error suggesting rundllproc and the TSV path.

W vs A: For functions that exist as a W/A pair, the table records the bare name and a default variant (almost always W). Type the suffix explicitly to override per-call without editing the table.

Safety: winapi inherits rundllproc's crash semantics. Wrong argument count or type can crash the shell. Prefer -d first to confirm resolution before chaining a call into a script.

See also

rundllproc, dllimport, dlllist, peinfo

winver back to top ↑

display Windows version

Synopsis

    winver

Options

    -s, --short    Print just the version number, for scripts.

Description

Displays detailed information about the currently running Windows version, including edition, version number, and build information.

Examples

    winver
        Display Windows version information.

Exit status

0       Success

Notes

Information Displayed: - Windows edition (Home, Pro, Enterprise, etc.) - Version number (e.g., 22H2) - Build number (e.g., 19045.3803) - Architecture (32-bit or 64-bit)

Version vs Build: - Version: Marketing version (21H2, 22H2, 23H2) - Build: Specific build number, changes with updates

For CSHW shell version, use 'version' or 'ver' instead.

See also

version, uname

writefile back to top ↑

write a shell variable's contents to a file

Synopsis

    writefile <variable> <file>

Description

writefile writes the contents of shell variable <variable> out to <file>, overwriting any existing file. It is the inverse of readfile.

The variable's text is written as-is; a trailing newline appears only if the variable's value already ends with one. The file is written as text, so LF line endings become CRLF.

Examples

    writefile report summary.txt
        Save $report to summary.txt.

    readfile data in.txt
    writefile data out.txt
        Copy a file's contents through a variable.

Exit status

0 on success; non-zero if the variable is not set or the file cannot be written.

See also

readfile, set, fileblob

xargs back to top ↑

build command lines from standard input and run them

Synopsis

    xargs [options] [command [initial-args...]]

Description

xargs reads items from standard input and runs <command> with those items appended as arguments. It is most often used at the end of a pipe to turn a list of names into arguments for another command:

ls *.tmp | xargs rm

If no <command> is given, echo is used. Input items are separated by whitespace (spaces, tabs, newlines) unless -0 or -d changes that. Without -n or -I, every item is passed to a single invocation.

Options: -n N pass at most N items to each invocation -I STR replace STR in the command with one input item, running the command once per input line -d C use character C as the item separator -0 items are separated by NUL (for `find -print0`) -t print each command line to stderr before running it -r do not run the command if the input is empty (long form: --no-run-if-empty)

Examples

    ls *.log | xargs rm

    echo a b c | xargs -n 1 echo

    cat filelist.txt | xargs -I F cp F backup/

Exit status

0 if every invocation succeeded, 1 if any invocation reported failure.

See also

echo, find, ls

zip back to top ↑

create a .zip archive (Windows-style)

Synopsis

    zip [/r] [/p[:<password>]] <archive.zip> <file_or_dir> [more...]

Description

Creates a .zip archive from the listed files and/or directories. Existing archives are overwritten. Entry paths inside the archive use forward slashes and are relative to each argument's leaf name (so `zip pkg.zip src` produces entries `src/...`, not absolute paths).

Supports password protection with AES-256 encryption via /p.

Options

    /r, --recursive
        Recurse into subdirectories when an argument is a directory.

    /p[:<password>]
        Encrypt entries with AES-256. Bare /p prompts on the console
        with confirm. /p:<value> uses the literal password (suitable
        for scripts; note the password ends up in process args and
        shell history).

    <archive.zip>
        Output path. Overwritten if it exists.

    <file_or_dir>...
        One or more inputs. Mix of files and directories ok.

Examples

    zip backup.zip src docs README.md
        Bundle two directories + a file.

    zip /r site.zip public
        Recursively archive the public/ tree.

    zip /p:s3cret secret.zip notes.txt
        Encrypted with literal password.

    zip /p secret.zip notes.txt
        Encrypted; prompts for password on the console.

Exit status

0       Archive created.
1       Bad arguments or I/O error (see stderr).

Notes

The Windows-style `zip` builds ZIP archives. For tar/tar.gz/tar.bz2, see `tar`. To extract or list, see `unzip`.

See also

unzip, tar