How to Exclude Specific Files During Folder Transfer with `--exclude` in Croc
Use croc send --exclude for case-insensitive substring matching to skip files containing specific patterns, or --exclude-file for exact relative-path matching to omit specific files by their precise location.
When transferring directories with the secure file transfer tool croc, you often need to prevent temporary files, system metadata (like .DS_Store), or sensitive documents from entering the transfer stream. According to the schollz/croc source code, the CLI provides two exclusion flags that integrate directly into the zip creation workflow, filtering unwanted paths before transmission begins.
Understanding the --exclude Flag
The --exclude flag enables case-insensitive substring matching against the zip path of each file during directory traversal. In src/cli/cli.go (lines 82-84), this flag is defined to accept comma-separated values that populate the excludeStrings slice.
When the ZipDirectory function in src/utils/utils.go walks the directory tree (lines 59-70), it converts each file's zip path to lowercase and checks if it contains any substring from excludeStrings. If matched, the file is omitted from the archive, or filepath.SkipDir is returned to prune entire directory branches.
Substring Matching Behavior
Because matching is case-insensitive and based on substrings, a pattern like tmp matches project/tmp/file.txt, TempData.csv, and /var/tmp/log. This makes it ideal for excluding file types or directory names regardless of their depth in the tree.
Using --exclude-file for Exact Path Matching
For precise exclusion of specific files, use the --exclude-file flag. Defined alongside --exclude in src/cli/cli.go and parsed at lines 345-356, this flag populates the excludeFiles slice.
In src/utils/utils.go (lines 72-80), the code normalizes each file's relative path from the source root and compares it for exact equality against entries in excludeFiles. This requires the full relative path (e.g., config/secrets.yaml) and will not match partial strings or different case variations unless specified exactly.
Practical Command Examples
Exclude any path containing the substring "tmp" (case-insensitive):
croc send --exclude "tmp" ./myfolder
Exclude multiple patterns using comma separation:
croc send --exclude "tmp,.DS_Store,.log" ./myfolder
Exclude specific files by exact relative path:
croc send --exclude-file "secret.txt,private/config.yaml" ./myfolder
Combine both flags for comprehensive filtering:
croc send \
--exclude "tmp,.DS_Store" \
--exclude-file "secret.txt,private/config.yaml" \
./myfolder
Technical Implementation Details
The exclusion logic resides in src/utils/utils.go within the ZipDirectory function's directory walk. The implementation uses two distinct slices populated from CLI input:
excludeStrings– Values from--exclude, split on commas (parsed insrc/cli/cli.golines 345-356).excludeFiles– Values from--exclude-file, processed similarly.
For each file encountered:
- The zip path is lowercased and checked for substring containment against
excludeStrings(lines 59-70). - The normalized relative path is compared for exact equality against
excludeFiles(lines 72-80).
If either check succeeds, the entry is skipped and excluded from the final transfer archive.
Summary
- Use
--excludefor flexible, case-insensitive substring filtering that matches anywhere in a file's path. - Use
--exclude-filewhen you need to exclude specific files by their exact relative path from the source root. - Both flags accept comma-separated lists and are processed during the
ZipDirectoryexecution insrc/utils/utils.go. - Exclusion occurs during archive creation, ensuring filtered files never enter the encrypted transfer stream.
Frequently Asked Questions
Can I use wildcards or glob patterns with --exclude?
No. As implemented in src/utils/utils.go lines 59-70, --exclude performs simple case-insensitive substring containment checks, not glob or regex pattern matching. The pattern *.log would only match files literally containing the string *.log, not files ending in .log. For precise path control, use --exclude-file instead.
What is the difference between --exclude and --exclude-file?
--exclude checks if the lowercase zip path contains the provided substring anywhere in the string, useful for filtering by extensions or common directory names. --exclude-file requires the exact normalized relative path (e.g., private/data.json) and performs an equality match, ensuring only that specific file is omitted.
Does --exclude work on directories?
Yes. Because the matching operates on the full zip path, a pattern like node_modules will match any path containing that directory name. When a directory matches the exclusion criteria, croc uses filepath.SkipDir to skip the entire directory tree, significantly improving performance by avoiding unnecessary file system walks into excluded branches.
Where are these flags defined in the croc source code?
The CLI flags are defined in src/cli/cli.go at lines 82-84, where they are bound to the command's option set. The parsing logic that splits comma-separated values into the excludeStrings and excludeFiles slices appears at lines 345-356. The actual filtering implementation that consumes these slices resides in src/utils/utils.go at lines 59-80 within the ZipDirectory function.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →