DOS Pattern Matching

AmigaDOS pattern matching differs fundamentally from Unix/Windows shell globbing. This article documents the exact syntax and the two-step API. Source: RKM §9.

Key difference: the shell does NOT expand wildcards

Unlike Unix shells (bash, zsh) or Windows CMD, the AmigaDOS shell does not expand wildcards. The filesystem doesn't either. Instead, the application must call dos.library pattern-matching functions to interpret wildcard patterns.

This means: if you type Dir #?.c in an Amiga shell, the Dir command receives the literal string #?.c and does the expansion itself via MatchFirst()/MatchNext().

AmigaDOS wildcard syntax

Token Meaning Unix equivalent
#? Any number of any characters *
% Single character ?
[abc] Any of characters a, b, c [abc]
[~abc] Any character EXCEPT a, b, c [!abc]
\| Alternation (OR) \| (regex)
() Grouping () (regex)
? Literal question mark (NOT a wildcard!) n/a
* Literal asterisk (NOT a wildcard!) n/a

Critical: * is NOT a wildcard in AmigaDOS. #? is. This is the most common mistake for developers coming from Unix.

The two-step API

Pattern matching is split into parse (tokenize the wildcard) and match (compare a string against the parsed pattern):

/* Step 1: Parse the wildcard pattern into tokens */
LONG ParsePattern(STRPTR pattern, STRPTR parsed, LONG parsedLen);
/* Returns: 1 = has wildcards, 0 = no wildcards, -1 = error */

/* Step 2: Match a string against the parsed pattern */
LONG MatchPattern(STRPTR parsed, STRPTR str);
/* Returns: TRUE = match, FALSE = no match */

The parsed buffer must be at least 2 * (strlen(pattern) + 1) bytes.

Case-insensitive variants: ParsePatternNoCase(), MatchPatternNoCase().

Filesystem iteration with MatchFirst/MatchNext/MatchEnd

struct AnchorPath *ap = AllocDosObject(DOS_ANCHORPATH, NULL);
ap->ap_Strlen = 0;   /* don't copy path name */

LONG err = MatchFirst("SYS:#?.c", ap);
while (!err)
{
    /* ap->ap_Info is a FileInfoBlock with:
       ap->ap_Info.fib_FileName — filename
       ap->ap_Info.fib_Size     — file size
       ap->ap_Info.fib_DirEntryType — >0 = directory, <0 = file
    */
    printf("%s\n", ap->ap_Info.fib_FileName);
    err = MatchNext(ap);
}
MatchEnd(ap);   /* MUST be called to clean up locks */
FreeDosObject(DOS_ANCHORPATH, ap);

Always call MatchEnd() even if no matches are found — it releases directory locks.

The AnchorPath structure supports recursive scanning via ap_BreakBits (set APB_DOWILDRAW to enable). Set ap_Flags with APF_DODIR to enter directories, APF_DIDDIR marks completion.

Pattern matching for non-file strings

The same API works for matching arbitrary strings (not just filenames):

char parsed[1024];
ParsePattern("#?hello#?", parsed, sizeof(parsed));
if (MatchPattern(parsed, "say hello world"))
    printf("match!\n");

This is useful for text searching, input validation, and filtering.

See Also


Sources: Thomas Richter, "ROM Kernel Reference Manual: AmigaDOS" (2024 edition), §9. Raw: raw/rkm/rkm-amigados-extract.md; raw/rkm/rkm-dos-book.md Updated: 2026-08-08