Copy a Directory Structure, Transfer Nothing! The rsync trick that feels like a bug but is a feature!
You need the same directory tree somewhere else but none of the files.
- Same structure.
- Same depth.
- Zero data.
cp -r fails tar feels heavy, custom scripts feel wrong.
Then comes this line — and it looks like it shouldn't work.
rsync -a -f"+ */" -f"- *" /source/path/ /destination/path/Yet it does. Perfectly.
The Problem Nobody Explains Clearly
You might need this when:
- Preparing empty environments (prod → staging)
- Rebuilding folder skeletons
- Migrating systems without sensitive data
- Creating directory templates for CI/CD pipelines
You don't want files, you want shape.
Why Rsync Is the Right Tool (Even Here)
Most people think of rsync as a file copier, It isn't, It's a filesystem synchronizer with a powerful filtering engine. The trick lies in understanding how rsync decides what exists.
Breaking Down the "Impossible" Command
rsync -a -f"+ */" -f"- *" /source/ /dest/-a (archive)
Preserves:
- permissions
- timestamps
- symlinks
- directory metadata
-f"+ */"
- Include only directories.
- The trailing
/matters. It tells rsync: this rule applies to directories only.
-f"- *"
- Exclude everything else — all files.
Order matters, Filters are processed top to bottom.
The Trailing Slash Trap (Don't Skip This)
/source/ → copies contents
/source → creates /dest/sourceIf you forget this, you'll replicate the wrong structure, This is the number one mistake.
What Gets Preserved (And When)
Permissions → Yes
Timestamps → Yes
Owner → Only if run as root
Group → Root or group member
ACLs → Add -A
Xattrs → Add -X
For maximum fidelity:
rsync -aAX -f"+ */" -f"- *" /source/ /dest/Want to See Before You Do?
Always dry-run first:
rsync -av -n -f"+ */" -f"- *" /source/ /dest/No surprises. No regrets.
The "Pure Bash" Alternative (When Rsync Isn't Available)
cd /source && find . -type d -exec mkdir -p /dest/{} \;It works. But you lose metadata and elegance.
Why This Feels Like a Cheat Code
This command:
- Copies structure, not data
- Avoids scripting
- Preserves intent
- Scales to massive trees
It looks like a bug, but it behaves like a feature, it saves hours!