Copy only folders not files?
Solution 1
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.
Solution 2
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))
Related videos on Youtube
Shannon
Updated on September 18, 2022Comments
-
Shannon almost 2 years
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!
-
Shannon over 10 yearsThis is me being a noob, however how are you searching the old dir to copy to the backup? I can only see one path here
-
Oli over 10 yearsIf you don't specify a path,
find
uses the current working directory as the starting point. If you wish to use another path use the syntax:find /path/to/search/ -type.....
-
Shannon over 10 yearsSo I set my directory to a certain folder that contains the skeleton I want to copy, run
find -type d -exec mkdir -p "/media/jinglez/TVSeries/TV Series"/{}" \;
and all should be okay? It seems to be taking a while :/ -
Shannon over 10 yearsI run this from normal terminal right?
-
Shannon over 10 yearsWhat does putting the path in quotes and the {} at the end of it mean? Also the \; I have never seen that in a terminal command before
-
Oli over 10 yearsThey're both specific to find's exec clause. {} means the current "found" filename and \; is just the escape to end the clause. By the looks of it, there's an extra " in your code up to no good, I'm sure... Should read:
find -type d -links 2 -exec mkdir -p "/media/jinglez/TVSeries/TV Series/{}" \;
-
Trevor Boyd Smith about 7 yearsPlease note this solution may copy the directory structure but this solution does not retain the directories' permissions and attributes. Use
rsync
to copy the directory structure AND retain the permissions and attributes](stackoverflow.com/a/9242883/52074).