Wildcard characters in AutoCAD

Wednesday, July 1, 2026

Selecting every object whose layer starts with WALL in one go, showing only your dimension layers, keeping just the blocks whose name ends in _2D… these tasks come up constantly in AutoCAD. The good news: you don't need to write any code for them. AutoCAD ships with a wildcard engine — close to regular expressions but far simpler — available right in the interface.

In this article we start from the everyday use of a standard user, then work our way up to developer use (AutoLISP and .NET). The key point: it is the exact same engine at every level. The patterns you learn with the mouse can be reused as-is in your scripts.

What does a pattern look like?

A pattern (or filter) is a string in which some characters carry a special meaning. The most common ones:

  • * stands for any sequence of characters (including an empty one);
  • ? stands for a single arbitrary character;
  • # stands for a single digit.

So WALL* means "anything starting with WALL", *_2D means "anything ending in _2D", and PLAN-### means "PLAN- followed by three digits". We'll see the full list further down; let's start by putting them to use.

Quick Select (QSELECT)

Quick Select (the QSELECT command, also available from a right-click in the drawing) lets you select objects based on their properties. When you filter on a text property — the layer name, the block name, some text… — the Matches wildcard operator turns wildcards on.

The Quick Select dialog filtering objects whose layer matches WALL*

For example, to select every object on a layer starting with WALL:

  1. run QSELECT;
  2. under Property, choose Layer;
  3. under Operator, choose Matches wildcard;
  4. under Value, type WALL*;
  5. confirm: all matching objects are selected at once.

Thanks to the comma, you can even target several families at the same time: WALL*,PARTITION*,COLUMN*.

Searching in the Layer Properties Manager

The Layer Properties Manager (the LAYER command) has a search box in its top-right corner that understands wildcards. Type a pattern to display only the matching layers.

The Layer Properties Manager search box filtered on WALL*

This is perfect for quickly locating a layer in a template that holds hundreds of them.

Layer property filters

One step beyond a simple search: layer property filters. Inside the Layer Properties Manager, they let you create groups that fill themselves automatically based on a pattern. Every layer whose name matches shows up in the filter, including those you create later.

Creating a layer property filter based on the pattern DIM*

A filter named "Dimensions" based on DIM* will automatically gather DIM, DIM-TEXT, DIM_2D… You then manage the visibility or the lock state of the whole group in a single move.

The same principle (a field that accepts wildcards) appears in many other dialog boxes: managing linetypes, styles, purging named items, and so on.

The full list of wildcard characters

Now that the principle is clear, here are all the special characters AutoCAD recognizes in a pattern:

Character Meaning
# (pound) A single numeric digit
@ (at) A single alphabetic character
. (period) A single non-alphanumeric character
* (asterisk) Any character sequence (including an empty one), at the start, middle, or end
? (question mark) A single arbitrary character
~ (tilde) As the first character of the pattern: matches anything except the pattern
[...] Any one of the enclosed characters
[~...] Any single character not enclosed
- (hyphen) Inside brackets: specifies a range of characters
, (comma) Separates two patterns (a logical OR)
` (reverse quote) Escapes the next character (reads it literally)

These characters work everywhere: in the interface fields shown above just as in the code we now turn to.

For developers: the (wcmatch) function in AutoLISP

Let's move to the programming side. In AutoLISP, this engine is exposed by the (wcmatch string pattern) function. It returns T if the string matches the pattern, and nil otherwise.

(wcmatch "PLAN-001" "PLAN*")        ; => T
(wcmatch "PLAN-001" "*001")         ; => T
(wcmatch "SECTION-002" "PLAN*")     ; => nil

It is the ideal tool to test user input, filter a list of names, validate a code… Let's go through each character.

* — any sequence

The most widely used wildcard. It stands for zero, one, or more characters, in any position:

(wcmatch "WALL_EXT_01" "WALL*")     ; => T   (starts with WALL)
(wcmatch "WALL_EXT_01" "*01")       ; => T   (ends with 01)
(wcmatch "WALL_EXT_01" "*EXT*")     ; => T   (contains EXT)
(wcmatch "WALL" "WALL*")            ; => T   (the sequence may be empty)

? — any single character

Unlike *, ? matches exactly one character:

(wcmatch "A1" "A?")                 ; => T
(wcmatch "A12" "A?")                ; => nil (two characters after A)
(wcmatch "SIDE" "SI??")             ; => T

# — a digit

The # accepts only a digit (0 to 9). Very handy to validate numbered codes:

(wcmatch "PLAN-007" "PLAN-###")     ; => T
(wcmatch "PLAN-XYZ" "PLAN-###")     ; => nil
(wcmatch "R12" "@##")               ; => T   (a letter followed by two digits)

@ — a letter

The @ accepts only an alphabetic character. Combined with #, it describes precise formats, such as a registration code or a reference:

(wcmatch "A320" "@###")             ; => T
(wcmatch "2320" "@###")             ; => nil (starts with a digit)

. — a non-alphanumeric character

The period matches a character that is neither a letter nor a digit (space, hyphen, underscore, punctuation…):

(wcmatch "A-1" "@.#")               ; => T   (letter, separator, digit)
(wcmatch "A_1" "@.#")               ; => T
(wcmatch "AB1" "@.#")               ; => nil (B is alphanumeric)

[...] — a set of characters

Brackets define a character set: at that position the string must contain one of the listed characters:

(wcmatch "PLAN" "[PC]LAN")          ; => T   (P or C)
(wcmatch "CLAN" "[PC]LAN")          ; => T
(wcmatch "VLAN" "[PC]LAN")          ; => nil

- — a range inside brackets

Inside brackets, the hyphen defines a range:

(wcmatch "C" "[A-F]")               ; => T
(wcmatch "M" "[A-F]")               ; => nil
(wcmatch "ROOM-5" "ROOM-[0-9]")     ; => T
(wcmatch "REV_C" "REV_[A-Z]")       ; => T

[~...] — an excluded character

A tilde at the start of the brackets inverts the set: the character must be different from those listed:

(wcmatch "PLANB" "PLAN[~A]")        ; => T   (the last character is not A)
(wcmatch "PLANA" "PLAN[~A]")        ; => nil
(wcmatch "X" "[~0-9]")              ; => T   (anything but a digit)

~ — global negation

Placed at the very beginning of the pattern, the tilde inverts the whole result: the string matches if it does not match the rest of the pattern:

(wcmatch "SECTION-01" "~PLAN*")     ; => T   (does not start with PLAN)
(wcmatch "PLAN-01" "~PLAN*")        ; => nil

, — several patterns (OR)

The comma lets you test several patterns at once. The function returns T if at least one of them matches:

(wcmatch "SECTION-02" "PLAN*,SECTION*,DETAIL*")   ; => T
(wcmatch "FACADE" "PLAN*,SECTION*,DETAIL*")       ; => nil

This is ideal to filter on a family of prefixes.

` — escaping a special character

What if you want to search for a character that is itself a wildcard? You escape it with a reverse quote (`). The character that follows is then read literally.

The classic example is AutoCAD's anonymous blocks, whose names start with * (such as *U2). To target the *U2 block exactly, without the asterisk being interpreted as a wildcard:

(wcmatch "*U2" "`*U2")              ; => T
(wcmatch "XU2" "`*U2")              ; => nil (the literal asterisk is required)

In the same way, to search for a string that really contains a #, a ?, or a comma, you prefix each of those characters with `.

Wildcards in ssget

The most frequent use of (wcmatch) is in fact indirect: it is built into ssget's selection filters. In a filter list, any DXF group code that carries a text value accepts wildcards directly: layer name (code 8), block name (code 2), linetype (code 6), and so on.

Here you don't need to call (wcmatch): AutoCAD applies the engine automatically. It is, in effect, the scripted version of the Quick Select we saw earlier.

Select every object whose layer starts with WALL:

(ssget "X" '((8 . "WALL*")))

Select on several layer prefixes at once thanks to the comma:

(ssget "X" '((8 . "WALL*,PARTITION*,COLUMN*")))

Select every block reference (INSERT) whose name ends in _2D:

(ssget "X" '((0 . "INSERT") (2 . "*_2D")))

Exclude a layer using the tilde (every object except those on the DIM layer):

(ssget "X" '((8 . "~DIM")))

The "X" tells ssget to scan the whole drawing database. You can also drop the "X" to combine these filters with an interactive selection: only the objects matching the pattern are then kept from what the user picks.

The .NET equivalent: WcMatchEx

On the .NET API side, the same engine is exposed — but in an internal namespace, which signals that it is not officially supported and could change. The signature is:

Autodesk.AutoCAD.Internal.Utils.WcMatchEx(string str, string pattern, bool ignoreCase);

It returns a bool and adds a genuinely useful argument: ignoreCase, to compare regardless of case.

using Autodesk.AutoCAD.Internal;

bool m1 = Utils.WcMatchEx("PLAN-007", "PLAN-###", ignoreCase: true);   // true
bool m2 = Utils.WcMatchEx("wall_ext", "WALL*", ignoreCase: true);      // true
bool m3 = Utils.WcMatchEx("wall_ext", "WALL*", ignoreCase: false);     // false

For instance, you can use it to list the layers in a drawing that match a pattern:

using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.Internal;
using Autodesk.AutoCAD.Runtime;

[CommandMethod("LISTWALLS")]
public void ListWallLayers()
{
    Document document = Application.DocumentManager.MdiActiveDocument;
    Database database = document.Database;
    Editor editor = document.Editor;

    const string PATTERN = "WALL*,PARTITION*";

    using (Transaction transaction = database.TransactionManager.StartTransaction())
    {
        LayerTable layerTable = (LayerTable)transaction.GetObject(database.LayerTableId, OpenMode.ForRead);

        foreach (ObjectId layerId in layerTable)
        {
            LayerTableRecord layer = (LayerTableRecord)transaction.GetObject(layerId, OpenMode.ForRead);
            if (Utils.WcMatchEx(layer.Name, PATTERN, ignoreCase: true))
                editor.WriteMessage("\n{0}", layer.Name);
        }

        transaction.Commit();
    }
}

Caution: WcMatchEx lives in Autodesk.AutoCAD.Internal. As its name says, this API is internal and is not guaranteed from one version of AutoCAD to the next. For selection filtering, prefer patterns directly in the ssget / SelectionFilter filters, which remain the official route. Reserve WcMatchEx for cases where you already hold the string (layer name, block name, user input) and want exactly the same wildcard semantics as the rest of AutoCAD.

In summary

AutoCAD's wildcard engine is a thread that ties everyday use to development:

  • on the user side, it is there from Quick Select, layer search, and layer filters — no code required;
  • on the developer side, you meet it again, identical, in (wcmatch), in the ssget filters, and in WcMatchEx in .NET.

The key characters: *, ?, #, @ and . cover the essentials; [...], [~...] and - refine character by character; ~ and , build complete filters; and ` escapes the wildcards themselves (think of the *U… anonymous blocks). Learn these patterns once, reuse them everywhere.


Helping hand Need an AutoCAD (AutoLISP, ObjectARX, .NET, VBA) development? Contact me for a free quote.

On the same topic