trash
Move files and folders to the system trash instead of permanently deleting them, with cross-platform glob support.
Repository Health
Technical Analysis
trash is a small Node.js library that moves files and directories to the operating system’s trash or recycle bin rather than deleting them outright. Where fs.unlink, del, and rimraf remove data permanently, trash gives users a safety net: mistakes made via a build script, CLI tool, or automated cleanup task can still be recovered from the Trash/Recycle Bin instead of being gone for good.
Under the hood it dispatches to a platform-specific implementation at call time — a native macOS binary (macos-trash) invoked via execFile, a bundled Windows executable (windows-trash.exe) that talks to the Recycle Bin, a pure-JS XDG-spec-compliant mover for Linux, and a dedicated WSL path that converts paths and shells out to PowerShell so files end up in the real Windows Recycle Bin. The public API is a single async function that accepts strings, arrays, and glob patterns, silently skipping paths that don’t exist so callers don’t need to pre-check file existence.
What You Get
- A single
trash(paths, options?)async function accepting strings, arrays of strings, and glob patterns via globby - Automatic platform dispatch to native macOS, Windows, Linux (XDG trash spec), and WSL implementations with no configuration required
- Non-existent files and empty glob matches are silently ignored rather than throwing
- Nested-path de-duplication so trashing a directory and a file inside it doesn’t double-process
- A permission-denied fallback on macOS that moves files into the user’s
.Trashfolder directly when the native binary can’t run - WSL-aware handling that splits paths between the real Windows Recycle Bin (via PowerShell) and a Linux-style trash fallback for
\\wsl$paths - TypeScript type definitions (
index.d.ts) shipped alongside the package
Common Use Cases
- Build tools and CLI utilities that clean up generated files but want the operation to be reversible if something goes wrong
- Desktop and Electron apps that need to “delete” user files the same way Finder/Explorer would, so users can recover them
- Test suites and scripts that clear out temp directories between runs without risking data an operator didn’t intend to lose
- CLI file managers (its companion
trash-clipackage is exactly this) that need a scriptable, safe alternative torm
Under The Hood
Architecture
The library is a thin dispatcher: index.js normalizes input paths (flattening, globbing via globby, filtering out nested paths and non-existent entries) and then delegates to exactly one of four platform modules under lib/ — macos.js, windows.js, linux.js, or wsl.js — chosen at call time by branching on process.platform (with a runtime check for WSL via wsl-utils). Each backend shares a small chunked-exec.js helper that batches paths into fixed-size groups before invoking a native binary, which keeps command-line length within OS limits. The design cleanly separates cross-platform path resolution (owned by index.js) from OS-specific trash semantics (owned by each lib/ module), so adding or altering support for one platform never touches the others.
Tech Stack
The package is pure ESM ("type": "module") targeting Node.js 20+, with no build step — it ships index.js and index.d.ts directly. Its dependencies are narrowly scoped utility packages, mostly maintained by the same author: globby for glob expansion, is-path-inside for nested-path filtering, move-file for cross-device-safe renames, p-map for bounded concurrency, xdg-trashdir for locating the correct XDG trash directory on Linux, @stroncium/procfs for reading /proc/self/mountinfo to resolve trash locations across mount points, and wsl-utils/powershell-utils for the WSL-to-Windows bridge. Platform binaries (macos-trash, windows-trash.exe) are vendored directly in lib/ rather than compiled at install time. Testing uses Node’s built-in node:test runner plus tsd for type-definition testing, linted with xo, and CI runs on GitHub Actions across Node 20/24 on Ubuntu and macOS.
Code Quality
test.js exercises the public API end-to-end against a real temporary directory rather than mocking the filesystem, covering literal paths, glob matching with negation, numeric/odd filenames, and nested-path scenarios. Error handling is explicit: ENOENT is swallowed when checking whether a path exists (the documented “missing files are ignored” behavior), but other filesystem errors are re-thrown rather than suppressed, and the macOS backend distinguishes a specific permission-denied error message before triggering its fallback path. The codebase is consistently linted with xo (a stricter ESLint preset) and ships type definitions validated by tsd, though there is no code coverage tooling and the four platform backends are only exercised on the OS actually running CI (Windows execution is currently commented out of the CI matrix).
API Design
The public surface is deliberately minimal — one function, one options object with a single glob boolean — which keeps the learning curve close to zero for anyone already familiar with promise-based Node APIs. Inputs are forgiving (accepts a single path, an array, numbers coerced to strings) and failure modes favor silence over exceptions for the common case of “the file was already gone,” which matches how a trash operation is expected to behave in cleanup scripts. The tradeoff is that callers wanting to know whether a specific file was actually trashed must check for its existence themselves, since the function returns no per-path result — documented explicitly in the README rather than left implicit.