Copy only folders not files?

Is there a way to copy an entire directory, but only the folders? I have a corrupt file somewhere in my directory which is causing my hard disks to fail.

So instead of copying the corrupt file to another hard disk, I wanted to just copy the folders, because I have scripts that search for hundreds of folders, and I don't want to have to manually create them all.

I did search the cp manual, but couldn't see anything (I may have missed it)

Say I have this structure on my failed HDD:

dir1 files dir2 files files dir4
dir3
files

All I a want is the directory structure, not any files at all.

So I'd end up with on the new HDD:

dir1 dir2 dir4
dir3

Hoping someone knows some tricks!

3

2 Answers

If you want to mirror a directory skeleton and copy no files:

find -type d -links 2 -exec mkdir -p "/path/to/backup/{}" \;

What's going on here:

  • Find is only selecting directories
  • We're using -links 2 to find the deepest possible directories.
  • mkdir -p will make any missing directories along the way.

I've done it like this rather than find -type d -exec mkdir -p "/path/to/backup/{}" \; because it'll cut out on a whole buttload of mkdir calls. We can quickly prove this with a little test. Here's the test tree followed by what I ran to compare the two commands:

$ tree
.
├── dir1
│   ├── dir2
│   │   └── dir3
│   ├── dir7
│   └── dir8
└── dir9 └── dir0
$ pr -m -t <(find -type d) <(find -type d -links 2)
. ./dir1/dir8
./dir1 ./dir1/dir2/dir3
./dir1/dir8 ./dir1/dir7
./dir1/dir2 ./dir9/dir0
./dir1/dir2/dir3
./dir1/dir7
./dir9
./dir9/dir0 

And that's only going to get better in a real-word solution with thousands of directories.

8

Quite easily done with python one-liner:

bash-4.3$ tree
.
├── ABC
├── set_pathname_icon.py
├── subdir1
│   ├── file1.abc
│   └── file2.abc
├── subdir2
│   ├── file1.abc
│   └── file2.abc
└── subdir3 └── subdir4 └── file1.txt
4 directories, 7 files
bash-4.3$ python -c 'import os,sys;dirs=[ r for r,s,f in os.walk(".") if r != "."];[os.makedirs(os.path.join(sys.argv[1],i)) for i in dirs]' ~/new_destination
bash-4.3$ tree ~/new_destination
/home/xieerqi/new_destination
├── subdir1
├── subdir2
└── subdir3 └── subdir4

As script this could be rewritten like so:

#!/usr/bin/env python
import os,sys
dirs=[ r for r,s,f in os.walk(".") if r != "."]
for i in dirs: os.makedirs(os.path.join(sys.argv[1],i)) 

Your Answer

Sign up or log in

Sign up using Google Sign up using Facebook Sign up using Email and Password

Post as a guest

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

You Might Also Like