OS 3.2 Shell Commands

AmigaOS 3.1.4 and 3.2 rewrote or updated most of the C: commands. For people writing install scripts, build scripts or system tools, the changes that matter are new keywords, changed output, and behaviour that now depends on the V47 dos.library (error output over pr_CES, VolumeRequestHook(), the V47 shell). This page lists those changes in table form, taken from the per-command release notes in NDK 3.2 R4. Shell syntax (redirection, pipes, variables) is covered in The AmigaDOS Shell.

Version numbers are the command's own; 45.x releases belong to the 3.1.4 project or earlier, 46.x/47.x to 3.2, as marked in the release notes.

General changes

Change Commands Notes
Error messages printed over pr_CES Assign, Copy, CPU, Dir, Eval, MakeLink and most others (45.x in the 3.2 project) Redirect with *>; PrintFault() uses pr_CES since dos 47.3.
$VER: cleaned up Assign, Copy, Eval, Rename … (47.x, Jan 2021) "Removed double $VER: strings, migrated to newer VERSTAG".
MatchFirst() anchor reset Copy, Join, Rename, Type, MD5Sum The AnchorPath is cleared and re-initialised before each MatchFirst(), since flags left by the last MatchNext() broke reuse. The same rule applies to your own code.
Soft links no longer confused with directories Dir, FileNote, SetDate
Backports from the 4.x code base List (51.20), MD5Sum (52.2), MountInfo (51.4), Protect (51.4), Owner (51.1), Type, Mounter (51.5)

Command reference

Files and directories

Command Version New or changed
Copy 45.2 Soft and hard links are re-created as links "to the same object, or a link of the same path" (follows Workbench).
45.4 Copying *: substituted by #? if the wildstar flag in the dos root node is set, otherwise fails (previously copied from the console).
47.1 FORCE keyword overwrites protected targets.
47.2–47.4 Copies metadata (protection bits, file notes) of directories too; applied to the target name, not the source name.
Dir 45.2–45.11 Marks soft links; column layout adapts to the console width; with non-interactive output the width is taken from the console *, so piping to more works.
47.2 If the object is exclusively locked, examines it from its parent directory.
List 45.4 No crash on names longer than 32 characters.
45.6 LFORMAT %r prints the target of soft and hard links (originally %i).
45.7 LFORMAT %Q: directory name without trailing slash (colon kept for devices).
45.9 Block size, key and block count printed unsigned (files > 2 GB).
47.8 LFORMAT %P; FLAT option.
47.12–47.15 LFORMATQUOTE (alias LFQ) with modes shell and wildcard: quotes names that need it when the LFORMAT spec is written in upper case (e.g. list lformat %S lformatquote shell). %o/%O give relative path plus name; %S%S is rewritten to %O so it is safe with quoting.
MakeDir 45.1 ALL creates intermediate directories.
MakeLink 2.0+ 44.1 SOFT/S creates soft links (the ignored HARD/S was removed). FORCE is used in the RAM: external-link recipe below.
SetDate 47.1 FROM copies the date from another file.
Protect 47.1 Backport of Protect 51.4.
Owner 47.1 Backport of Owner 51.1.
Rename 1.3+ 45.1 Allocates its memory in one piece.
Relabel 2.0+ 47.2 Checks the 30-character volume name limit and the trailing colon.
Which 45.2 For an argument ending in : just prints the volume name.

Searching, viewing and checksums

Command Version New or changed
Search 45.2–45.4 CASE for case-sensitive search (inactive when searching for files); locale-aware case folding via ParsePatternNoCase(); non-FILE search strings up to 1024 characters (255 for FILE).
Type 45.1 Works as a filter in a pipe.
47.2 Adds AUTO, TEXTONLY, WIDTH and BUFFER options; output is unmodified unless HEX or NUM is used (NUL bytes no longer truncate).
Find 47.12 STRING option (search inside files) exposed on the command line and as tool type.
MD5Sum 47.1 New command.
47.2 CHECK compares recorded checksums correctly.
47.5–47.6 Raw partition/disk reads: buffer defaults to two tracks (max 65536, limited by MaxTransfer); BUFFERSIZE overrides it. DISKACCESS (AUTO, NSD64, TD64) selects the command for disks larger than 4 GiB, matching Disk Doctor.
47.4 File names containing wildcard characters are not supported.
Eval 45.2 Real recursive-descent parser: operator priorities are now correct.

System information

Command Version New or changed
Version 45.1 Scans the seglists of mounted file systems; RAW:, CON:, RAM: map to their ROM module names; an unloaded handler (PAR:, PRT:, SER:) is checked from its handler file.
45.3 workbench and icon versions read from disk if available.
45.4–45.5 A path argument switches to file version information; device names still work.
45.6, 47.1 $VER scanner fixed (missed valid tokens, looped near end of file); optimized scanner backported from Workbench.
CPU 45.1 68060 support and feature detection; CPU errata tests; FASTROM/NOFASTROM/TRAP/NOTRAP are dummies.
45.5 CHECKINSTALL tests for the presence of a CPU library on CPUs that need one.
45.7 CPUTYPE, FPUTYPE, MMTYPE (spelling as in the release note) print minimal output for scripts; TO redirects output.
46.1 Test for the 68060 F6 bug (besides I4).
AmigaModel 45.1 / 47.1 New command for model detection; CDTV detection added in 47.1.
MountInfo 47.1 New command. 47.2 handles GlobVec = 0 "in debug mode and when building mount files" and checks whether dn_Startup holds a small integer.
ShowConfig 46.3–47.x Checks the FPGA bit (AFF_FPGA); ReAction GUI (GUI switch from the Shell); DEBUG mode restored.
Avail 47.1 Sizes printed as unsigned.
Status 45.1 Command buffer overrun fixed.

Processes and scripting

Command Version New or changed
Wait 1.3+ 45.1 FILE/K: wait until a file exists.
Break 45.1 Break a process by name or wildcard.
ChangeTaskPri 45.1 Change a process by name or wildcard.
Date 47.2 Error output and examples formatted for the current locale.
CLI / NewShell 47.x Created through System() with SYS_CmdStream/SYS_Asynch and SYS_InName (shell opens its own console); requires dos V47. NewShell no longer prints the new CLI number.
Reboot 45.1 Checks for running validation before rebooting.

Disks and assigns

Command Version New or changed
Assign 45.2 Assign names limited to 30 characters.
45.10 LIST DENIED shows volume requests denied through AssignWedge.
47.4 Assigning a name that AssignWedge has denied removes it from the denied list.
AssignWedge 47.1 New: client of VolumeRequestHook() (see below).
47.8 QUIT terminates a running instance; can be started from Workbench.
Format 2.0+ 45.2 / 46.1 Long file name support (DOS\8, replaced by DOS\6/DOS\7); enabled only for FFS ≥ V46. Long names imply international mode and no directory cache.
46.7 Uses DirectSCSI and TD64 as configured.
Install 45.2 Long-filename FFS variants; walks the DOS list instead of hard-coding DFx:.
47.2–47.4 CHECK returns RETURN_WARN for a non-bootable boot block and RETURN_ERROR for a bootable one without original Commodore boot code; trackfile.device on the device whitelist; reports "unknown file system" for DOS types beyond DOS\8.

Version and $VER

Version looks for the $VER: token in files, in resident modules and in the seglists of mounted handlers. Since 45.4, Version <path> reports the file version rather than a module version, and since 45.5 a device name still reports the device. system-startup creates a $VER: tag in the dummy startup segment of modules it loads from disk "to please the version command".

The $VER: and $STACK: cookie formats are described in Hunk Version and Stack Cookies.

AssignWedge and VolumeRequestHook

dos.library 47.4 added VolumeRequestHook() "to enable relaying DOS Volume mount requests to external programs ('AssignWedge')":

LONG VolumeRequestHook(CONST_STRPTR vol);   /* D1, LVO -1014, V47 */

dos.library calls it itself "in case a program attempts to access a volume that is currently not mounted or not inserted". The argument is the volume name as a NUL-terminated C string without the colon. Result:

Return Meaning
-1 Show the default "Please insert volume" requester (what the built-in function always returns).
0 Abort: cancel the request.
1 Retry the access.

The 2024 RKM (§16.2.2) documents only two results: DOSTRUE (−1) shows the requester, DOSFALSE (0) suppresses it as if the user pressed Cancel; it does not mention 1.

"A user supplied application may replace this function and thus provide a more elaborate requester." AssignWedge is that application: it offers Assign, Deny and Cancel, keeps a list of denied volumes, and exposes its global data (including the denied list) through its task's tc_UserData — which is how Assign LIST DENIED reads it. Its task name is << AssignWedge >>.

Lessons recorded in the AssignWedge release notes for anyone writing a replacement:

  • The hook runs in the context of the process that touched the volume. AssignWedge sends a message to its own process; the message is created on the stack.
  • Protect access to the reply port with Forbid()/Permit() against the port going away; check for an already-set signal before waiting.
  • If the wedge process itself triggers the hook, return immediately instead of waiting for itself.
  • Answer still-pending requests before shutting down.
  • Compare device names case-insensitively.
  • Preload strings for requesters to avoid deadlocks, and do not defer opening asl.library to inside the hook: AssignWedge 47.14 reverted that change "because assignwedge freezes if ramlib needs to load asl.library from disk at that time."

A minimal replacement installed with SetFunction() (SAS/C register syntax):

#include <dos/dosextens.h>
#include <proto/exec.h>
#include <proto/dos.h>
#include <proto/utility.h>

#define LVO_VolumeRequestHook (-1014)

struct Library *UtilityBase;
static APTR OldHook;

/* Called by dos.library on the accessing process: keep it short. */
static LONG __asm __saveds NewHook(register __d1 CONST_STRPTR vol)
{
    if (Stricmp(vol, "Scratch") == 0)
        return 0;                      /* never ask for this volume */
    return -1;                         /* default requester */
}

int main(void)
{
    if (DOSBase->dl_lib.lib_Version < 47)
        return 20;
    if (!(UtilityBase = OpenLibrary("utility.library", 37)))
        return 20;

    Forbid();
    OldHook = SetFunction((struct Library *)DOSBase, LVO_VolumeRequestHook,
                          (APTR)NewHook);
    Permit();

    Wait(SIGBREAKF_CTRL_C);

    Forbid();
    SetFunction((struct Library *)DOSBase, LVO_VolumeRequestHook, OldHook);
    Permit();
    /* other code may have patched over us: a real tool must check that
       before unloading, and must not exit while a call is in progress */
    CloseLibrary(UtilityBase);
    return 0;
}

Only one program should own the hook; with AssignWedge running, chain to OldHook instead of returning -1.

Shell built-ins and variables

The V45–V47 shell (L:Shell-Seg) includes these built-in commands and switches that scripts may use:

Built-in / feature Version Notes
Path ... HEAD 45.1 Adds paths to the start of the search path.
PushCD, PopCD, SwapCD 45.2 Directory stack; integrated into CD in 47.33. CD no longer accepts soft links as targets (47.33).
UnSetEnv ... SAVE 45.2 Makes the deletion permanent.
Ask 45.2 Numeric and string input; result to stdout or a local variable.
( 46.1 Resident command that runs its contents as a sub-shell.
History 47.6, 47.26 Built-in history command; keywords to load and save the history.
Fault 2.0+ 47.33 Prints decoded faults over stdout (COS), not stderr.
Why 47.13, 47.43 Output not through PrintFault; prints "Last command failed because: ".
#! / ;! scripts 45.0 A script file (s bit set; the e bit is not required) starting with these names its interpreter on the rest of the first line.
h bit 45.0 A command with p and h set is made resident automatically the first time it runs. The feature first appeared in V39, was dropped in V40 for lack of ROM space and returned in V45.
$STACK: 45.0 The shell scans the first 1K of each segment for $STACK:<bytes> and raises the stack for that command only.

Shell variables added in 47.x:

Variable Effect
simpleshell on disables TAB expansion and history (scripts disable it anyway).
debug on sends executed commands to the serial port (captured by syslog).
histskipdups Boolean: do not store duplicate commands in the history (added in 47.35).
NOLISTSKIPDUPS Release notes 47.37: skipping duplicates became the default and this variable keeps them. The 2024 RKM documents only histskipdups, which must be set to skip duplicates.
SHELLCOMPLETION Local variable selecting the TAB completion behaviour; accepts EARLYLISTING and ICONSASFILES (renamed from NOINFOEXCEPTION in 47.47).

TAB completion needs the CON-Handler's medium mode (SetMode(fh, 2)); see OS 3.2 File System and Handler Changes. Programs can call the shell's TAB expansion and history through DoShellMethod() — see The AmigaDOS Shell.

Recipes for install scripts

Mirror ENVARC: lazily into RAM (ram-handler 47.1):

MakeLink RAM:ENV to ENVARC: Force
Assign ENV: RAM:ENV

Create a directory tree and copy over write-protected files:

MakeDir SYS:Programs/MyApp/Data ALL
Copy MyApp:Data/#? SYS:Programs/MyApp/Data FORCE

Since Copy 47.2 directory protection bits and file notes are copied as well.

Wait for a file produced by a background job:

Wait FILE T:myjob.done

See Also


Sources: NDK 3.2 R4 ReleaseNotes/version-RelNotes, Assign-RelNotes, AssignWedge-RelNotes, MakeLink-RelNotes, List-RelNotes, Copy-RelNotes, Dir-RelNotes, Eval-RelNotes, MD5Sum-RelNotes, Which-RelNotes, CPU-RelNotes, AmigaModel-RelNotes, MountInfo-RelNotes, Wait-RelNotes, MakeDir-RelNotes, SetDate-RelNotes, Search-RelNotes, Type-RelNotes, Find-RelNotes, Protect-RelNotes, Owner-RelNotes, Rename-RelNotes, Relabel-RelNotes, Break-RelNotes, ChangeTaskPri-RelNotes, Date-RelNotes, Avail-RelNotes, Status-RelNotes, Reboot-RelNotes, ShowConfig-RelNotes, CLI-RelNotes, Format-RelNotes, Install-RelNotes, Join-RelNotes, shell-RelNotes, ram-handler-RelNotes, DOS-RelNotes, system-startup-RelNotes; Autodocs/dos.doc (VolumeRequestHook); SFD/dos_lib.sfd; Include_I/lvo/dos_lib.i; Thomas Richter, Amiga ROM Kernel Reference Manual: AmigaDOS (2024, v1.27), §15.1.6 (p. 318), §15.1.9 (pp. 319–320), §15.2.1 (pp. 325–326), §16.2.2 (p. 362) Updated: 2026-11-13