copy-no-nm
v0.26.23
Published
Copy from one folder to another without the nested node_modules folder
Downloads
33
Maintainers
Readme
copy-no-nm
Recursively copy a directory to another location while skipping every node_modules folder. By default the tool synchronizes the destination with the source (copies only new or changed files and removes extras). Use -f / --full for a full copy that clears the destination via the Recycle Bin first. File metadata (creation time, modification time, access time, attributes) is preserved on copied items.
Built with Go. Distributed on npm with a small Node.js launcher.
- Repository: github.com/maxzz/to-copy-no-nm-cli
- npm package: npmjs.com/package/copy-no-nm
Install from npm:
npm install -g copy-no-nm
# or
pnpm add -g copy-no-nmContents
Requirements
- Windows (Recycle Bin integration and metadata preservation use Windows APIs)
- Go 1.22+ for building from source
- pnpm for npm scripts
Usage
copy-no-nm [options] <source> <destination>Example:
copy-no-nm "C:\projects\my-app" "D:\backups\my-app"On start the program prints its name, a short description, and the version (for example copy-no-nm — Copy a folder… (version 0.26.2)).
Paths
| Path | Rule |
|------|------|
| <source> | Must exist and be a directory (second argument when -r / --reverse is on) |
| <destination> | Created automatically if it does not exist (including parent folders); if it already exists, it must be a directory. With -c / --check, the destination must already exist. First argument when -r / --reverse is on. |
By default arguments are <source> <destination>. With -r / --reverse, pass <destination> <source> instead.
Source and destination must be different paths and cannot contain each other.
Options
| Flag | Default | Description |
|------|---------|-------------|
| -f, --full | off | Full copy: clear the destination via Recycle Bin, then copy every file |
| -r, --reverse | off | Treat the first argument as destination and the second as source |
| -c, --check | off | Verify source and destination match (file size and modification time); excludes node_modules and .git; does not clear or copy |
| -g, --copy-git | off | Copy the .git folder from the source root and clear the destination .git folder |
node_modules is never modified in the destination and is always skipped during the copy. This is intentional — node_modules should be recreated by your package manager (especially with pnpm, which uses links inside that folder).
Examples:
# Default: keep destination node_modules and .git; skip copying source .git
copy-no-nm "C:\projects\my-app" "D:\backups\my-app"
# Destination folder does not exist yet — it will be created
copy-no-nm "C:\projects\my-app" "D:\backups\new-folder"
# Also sync the root .git folder
copy-no-nm -g "C:\projects\my-app" "D:\backups\my-app"
# Full copy: clear destination then copy everything
copy-no-nm -f "C:\projects\my-app" "D:\backups\my-app"
# Verify source and destination match (no changes made)
copy-no-nm -c "C:\projects\my-app" "D:\backups\my-app"
# Reverse argument order: destination first, source second
copy-no-nm -r "D:\backups\my-app" "C:\projects\my-app"Run without arguments (or with -h) to see in-program help: usage syntax, options with default values, and wrapped descriptions (~80 columns).
Process overview
Sync mode (default)
Synchronizes the destination with the source using file size and modification time:
- Copies files that are new in the source or differ from the destination
- Removes files present in the destination but absent from the source (via Recycle Bin)
- Skips unchanged files
- Preserves
node_modulesfolders in the destination (never scanned, deleted, or compared) - Skips the root
.gitfolder unless-g/--copy-gitis on (same rules as copy)
Full copy mode (-f, --full)
Each run performs two steps: clear destination, then copy from source.
Step 1 — Clear destination
| Item in destination | Default (-g off) | With -g |
|---------------------|--------------------|-----------|
| Files at any level | Recycle Bin | Recycle Bin |
| node_modules folders | Always kept (contents not scanned) | Always kept (contents not scanned) |
| Root .git folder | Kept | Recycle Bin |
| Other subfolders without nested node_modules | Recycle Bin (whole folder) | Recycle Bin (whole folder) |
| Subfolders containing nested node_modules | Cleared recursively with same rules | Cleared recursively with same rules |
node_modules folders in the destination are never deleted or inspected.
Step 2 — Copy from source
| Item in source | Default (-g off) | With -g |
|----------------|--------------------|-----------|
| All files and folders | Copied | Copied |
| node_modules folders (anywhere) | Skipped | Skipped |
| Root .git folder | Skipped | Copied |
File creation dates, timestamps, and attributes are preserved on copied items (including read-only files such as git objects).
Check mode (-c, --check)
Compares every file under source and destination using file size and modification time. Folders named node_modules or .git are ignored at any depth. The destination must already exist. Nothing is cleared or copied.
Reports the first mismatch (missing, extra, or different file) or prints a green summary when all compared files match.
Console output
| Situation | Behaviour | |-----------|-----------| | Missing or invalid arguments | Yellow help text with syntax, options, and defaults; press any key to close | | Check failed | Inspector Gadget in red, error message, press any key to close | | Check passed | Green summary with file count, then the app closes | | Runtime error | Inspector Gadget in red, error message, press any key to close | | Copy or sync success | Inspector Gadget in green for 1.5 seconds, then the app closes |
Development
Install dependencies (no runtime npm packages; pnpm is used for scripts only):
pnpm installBuild the Windows executable. The build script:
- Generates
assets/icon.icofromassets/icon-source.png(only if the.icofile is not already present) - Bumps the patch version in
package.jsonand syncsversioninfo.json - Embeds the icon and version metadata via
goversioninfo - Compiles
dist/copy-no-nm.exe
pnpm run buildRun directly:
.\dist\copy-no-nm.exe <source> <destination>Or via the npm bin shim after linking:
pnpm link --global
copy-no-nm <source> <destination>Debugging
Install the Go extension and Delve:
go install github.com/go-delve/delve/cmd/dlv@latestUse .vscode/launch.json for ready-made configurations (F5 in Cursor/VS Code). Debug builds use version dev unless you set -ldflags manually.
Windows shortcut
Create a shortcut and set Target to run the executable with preset arguments, for example:
C:\y\w\2-web\0-dp\utils\to-copy-no-nm-cli\dist\copy-no-nm.exe "C:\y\w\2-web\0-dp\utils\pmac" "C:\Users\maxzz\Desktop\pmac"Double-clicking the shortcut runs the copy with those paths.
npm scripts
| Script | Description |
|--------|-------------|
| pnpm run build | Bump version, generate icon (if needed), embed Windows resources, build dist/copy-no-nm.exe |
| pnpm run prepublishOnly | Build before publish (runs automatically on npm publish) |
| pnpm run publish:npm | Publish to npm (--access public) |
Publishing to npm
Published as copy-no-nm. Source code: maxzz/to-copy-no-nm-cli.
This package ships a prebuilt Windows binary in dist/ plus a Node launcher in bin/copy-no-nm.js.
pnpm run build
pnpm run publish:npmReplace the icon by editing assets/icon-source.png, then run pnpm run build again.
License
MIT
