Skip to content

dctl purge

Remove a path and all of its contents.

Synopsis#

dctl purge removes everything: every object beneath REMOTE:PATH, at every depth, plus the directories themselves. It is the widest blast radius in the tool, and dctl purge vault: means the entire remote.

This command ignores filters. That is the distinction rclone users expect, kept exactly:

  • delete honours filters and leaves the directory structure standing. dctl delete --include '*.tmp' vault:project removes the scratch files.
  • purge ignores filters and removes the tree. dctl purge vault:project removes the project.

Because filters are ignored rather than unsupported, passing --include, --exclude, --filter-from, --files-from, --min-size or --max-size to a purge prints a warning on stderr:

sh
warning: purge ignores filters: the whole tree goes. Use `dctl delete` to remove
a filtered subset.

Silence would be worse than noise. A user who believes --exclude 'keep/**' protected something is a user who is about to lose it.

The extra gate. Every removal command is destructive, but this is the only one that refuses a bare invocation. Everywhere else, running non-interactively counts as consent — you typed the command, which is enough for one file or one filtered set. A whole tree is not one file, so purge demands that the consent be explicit and fails with exit code 1 otherwise:

sh
error: refusing to purge 'vault:project': it removes everything under this path
warning: Pass --force to approve it, --interactive to be asked first, or
--dry-run to see what it would cover. Use `dctl delete` if you meant to remove
objects and keep the directories.

Purging a bare remote says so in as many words — the message reads it removes the entire remote rather than everything under this path. --dry-run is exempt from the gate: refusing to let you preview a purge would be hostile, and a preview removes nothing.

Target resolution is the family's strict parse. A remote name must be at least two characters, so C:\projects\apollo is a Windows drive path and is refused, as are UNC paths (\\server\share), bare local paths, and anything containing a .. component — the last of these matters more here than anywhere else in the family, since .. on a tree removal is how a typo escapes the subtree you meant. The surviving path is cleaned and NFC-normalised, so vault:project/, vault:./project and vault:project are one target.

Relationship to the verified-write contract. A purge writes nothing, so --verify, --checksum and --size-only have no effect and exit code 20 (checksum_mismatch) cannot be produced. The contract's rule that survives here is the honesty one from PLAN.md §6: nothing is reported that did not happen. The --dry-run plan carries no object list and no counters — only the resolved request and "status": "planned".

A purge is not recoverable by DCTL. There is no trash, no undo and no snapshot in this build; whether a deleted object can be resurrected depends entirely on the provider (B2 lifecycle rules, bucket versioning). If versioning is on, note that cleanup --class versions is the command that would later destroy those survivors too.

What runs today#

The tree removal runs. The recursive enumeration this command needs shipped with the listing family, and purge removes the path and everything beneath it:

sh
$ dctl purge vault:r2 --force
Command  purge
Target   vault:r2
Mode     execute
removed             12 B  r2/b.txt
removed              8 B  r2/sub/c.txt
OK removed: 2 object(s), 20 B

A path that holds nothing is exit 3 (dir_not_found) with a note saying so, not a silent success.

Earlier revisions of this page said the removal "is not implemented in this build" and quoted an exit-7 refusal that no build now produces. For the most destructive verb in the tool, that understatement is the worst possible drift — it reads as a safety net, and there is none.

sh
dctl purge REMOTE:PATH [flags]

Examples#

Every example below runs in this build and removes what it names. Earlier revisions of this page prefaced them with an engine refusal that no longer exists.

Preview a tree removal. No approval flag is needed for a preview, because a preview removes nothing:

console
$ dctl purge b2prod:bucket/media/2019 --dry-run
warning: [dry-run] would purge: b2prod:bucket/media/2019
Command  purge
Target   b2prod:bucket/media/2019
Mode     dry-run

A bare purge is refused. This is the gate that distinguishes purge from every other removal command:

console
$ dctl purge vault:projects/apollo
error: refusing to purge 'vault:projects/apollo': it removes everything under this path
warning: Pass --force to approve it, --interactive to be asked first, or
--dry-run to see what it would cover. Use `dctl delete` if you meant to remove
objects and keep the directories.
$ echo $?
1

Approve it explicitly. --force is the scriptable "yes, all of it"; --interactive prompts on stderr and requires the exact word yes. Past the gate the tree is gone:

console
$ dctl purge vault:projects/apollo --force
Command  purge
Target   vault:projects/apollo
Mode     execute
removed             6 B  projects/apollo/a.txt
removed            12 B  projects/apollo/b.txt
OK removed: 2 object(s), 18 B
$ echo $?
0

Filters do not narrow a purge, and DCTL says so rather than letting you believe otherwise:

console
$ dctl purge vault:projects/apollo --exclude 'keep/**' --force
warning: purge ignores filters: the whole tree goes. Use `dctl delete` to remove
a filtered subset.

Purging a whole remote is legal and is described as such. The JSON plan has no filters key at all — that absence is how a machine consumer sees that none applied:

console
$ dctl purge archive: --dry-run --json
{
  "command": "purge",
  "target": {
    "remote": "archive",
    "path": ""
  },
  "dry_run": true,
  "options": {},
  "status": "planned"
}

A Windows drive path is local, and no removal command accepts one — a one-character prefix is always a drive letter, on every platform:

console
$ dctl purge C:\projects\apollo --force
error: 'C:\projects\apollo' is a local path, not a remote
warning: The removal commands operate on a remote, written REMOTE:PATH. Use your
operating system's own tools to remove local files.

Options#

sh
  -h, --help   help for purge

The positional argument is <REMOTE:PATH>: the path to remove, with all of its contents. Filters are ignored. This command has no options of its own — the approval it requires comes from the global --force / --interactive flags.

Options inherited from parent commands#

Every global flag is accepted; see ../GLOBAL_FLAGS.md. The ones that matter here:

FlagEffect here
--forceApproves the purge without prompting. Required (or --interactive) for any non-dry run.
-i, --interactivePrompts before the purge; requires typing yes. Conflicts with --force.
-n, --dry-runPrint the plan and change nothing. Exempt from the extra gate; overrides --force.
--format, --jsonRender the --dry-run plan as a table, one JSON document, or one JSON Lines record.
--quietSuppresses the ignored-filter warning and the [dry-run] notice. Errors are still printed.

The filter flags are accepted, ignored, and warned about. --immutable is not yet consulted by the removal family — do not rely on it to protect a vault from dctl purge.

Exit codes#

See ../EXIT_CODES.md for the full contract.

CodeNameWhen
1usageUnparseable command line; a local, UNC, malformed-remote, empty or ..-containing target; a run with neither --force nor --interactive nor --dry-run; --interactive with no terminal to prompt on.
3dir_not_foundThe path holds nothing, so there is nothing to purge.
7fatal_errorThe remote is not configured and is not a known provider.
22vault_lockedWrong password or recovery phrase, or a damaged envelope.
23index_errorThe encrypted index or its journal could not be read or written.
25cancelledAn interactive confirmation was declined, or the run was interrupted with Ctrl-C.

Exit 0 means the tree was removed. An earlier revision of this table said 0 "is not currently reachable" and that every run past the gates ended at 7; neither is true, and 3 is produced today rather than being owed. 6 (partial_failure) remains unreachable — a tree is removed object by object and a failure part-way through is reported as an error rather than a partial success.

See also#

  • dctl delete — remove objects by filter and keep the directories.
  • dctl deletefile — remove exactly one named object.
  • dctl rmdir — remove one directory, and only if it is already empty.
  • dctl rmdirs — sweep the empty directories under a path.
  • dctl cleanup — reclaim abandoned uploads, staging litter and old versions.
  • dctl size — see how much a tree holds before purging it.