Copy folder structure (without files) from one location to another
Asked Answered
M

18

148

I want to create a clone of the structure of our multi-terabyte file server. I know that cp --parents can move a file and it's parent structure, but is there any way to copy the directory structure intact?

I want to copy to a linux system and our file server is CIFS mounted there.

Miseno answered 1/11, 2010 at 23:30 Comment(2)
Possible duplicate of Rsync how to include directories but not files?Passepartout
rsync solution from the above comment post looks neater.Chunky
U
235

You could do something like:

find . -type d > dirs.txt

to create the list of directories, then

xargs mkdir -p < dirs.txt

to create the directories on the destination.

Uneventful answered 1/11, 2010 at 23:37 Comment(11)
This solutions won't work if you have spaces in your directory names.Twain
@Twain Change the commands to find . -type d -print0 >dirs.txt and xargs -0 mkdir -p <dirs.txt. This will cause both commands to use nulls as separators instead of whitespace.Consignment
xargs can exceed the maximum command length of the system when you start dealing with orders of hundreds or thousands, so use this with caution. (Find the command length limit with getconf ARG_MAX.) With a lot of directories, you may have to write a script to loop through the output instead.Mcgannon
Note that the order of -type d and -print0 is important!Kelpie
this is a nice little find. thank you greg. thank you internet.Manlike
And what about permissions & attributes will it be retained ??Jaguarundi
@AshishKarpe and all the other people who voted up this answer: permissions and attributes are NOT retained... because you are doing a naive mkdir -p ${x} where x is each directory in the list. Use rynsc to preserve the permissions and attributes.Passepartout
@TrevorBoydSmith: Thanks for your comment. The original question didn't mention anything about needing to preserve permissions, ownership, or attributes. Doing so would require a different solution, as you mention, but the above is sufficient to answer the question as posed.Uneventful
@GregHewgill you are correct that your answer fulfills all the requirements in the given question. However, in practice, the many times I have "needed" to copy a directory structure... I have ALSO needed the same permissions/attributes that is why I left a link to the rsync solution.Passepartout
I do prefer the solutions using rsync rsync -a --include '*/' --exclude '*' "$source" "$target"Chromolithography
Thanks @Chromolithography looks like this will work while preserving permissions and hardlinks (-H)Biamonte
B
102
cd /path/to/directories &&
find . -type d -exec mkdir -p -- /path/to/backup/{} \;
Bethought answered 1/11, 2010 at 23:39 Comment(4)
Best answer from me with find. Else you can try rsync solution from Chen Levy answer in this SO questionHortensehortensia
What does the -- mkdir's option?Fearnought
-- is a standard GNU utility option terminator. It means "hey mkdir, any argument after this, it's not a flag, so treat it as a file argument, even if it starts with a '-' character."Bethought
this answer also does not retain the directory permissions and attributes. Use rynsc to preserve the permissions and attributesPassepartout
M
67

Here is a simple solution using rsync:

rsync -av -f"+ */" -f"- *" "$source" "$target"
  • one line
  • no problems with spaces
  • preserve permissions

I found this solution there

Materialism answered 30/8, 2017 at 12:7 Comment(4)
same but more readable rsync -a --include '*/' --exclude '*' "$source" "$target"Chromolithography
Problem with this solution is: my folders contain thousands of files and rsync takes ages just to sync a dozen of folders.Umbrella
Very nice! I used it with recursively with -r. In my experience rsync is fast as long it does not work on network file systems. In that case better use it's integrated ssh.Garnish
Any idea how to exclude hidden directories?Sextodecimo
S
14

1 line solution:

find . -type d -exec mkdir -p /path/to/copy/directory/tree/{} \;
Spreadeagle answered 8/7, 2020 at 12:46 Comment(1)
This works fine and works smartly. One wrinkle ylu must be in the $source directory to ensure your new tree is relative to the $target directory. But that's not one-line any more. Use: pushd $source; find . -type d -exec mkdir -p "$target"/{} \; popdStannfield
P
10

I dunno if you are looking for a solution on Linux. If so, you can try this:

$ mkdir destdir
$ cd sourcedir
$ find . -type d | cpio -pdvm destdir
Pravit answered 1/11, 2010 at 23:41 Comment(3)
cpio doesn't seem to work for me, at least with the parameters you specified.Miseno
@Miseno - please read the manual for cpio or refer gnu.org/software/cpioPravit
Could you please tell me what does -pdvm do? I tried the man cpio command but no avail.Karakul
R
9

This copy the directories and files attributes, but not the files data:

cp -R --attributes-only SOURCE DEST

Then you can delete the files attributes if you are not interested in them:

find DEST -type f -exec rm {} \;
Regin answered 27/12, 2015 at 17:15 Comment(3)
Would be exellent one, but you forgot to mention saving ownership, timestamp and permissions. So it produced a mess in Win7/cygwin - NULL_SID user, wrong permissions order, cannot edit permissions, etc and cannot access produced filestructure.Heptameter
I should think the blame lies squarely on whoever tries to use Windows for real work.Mariellamarielle
cp -R --attributes-only --preserve=all --parents -v SOURCE DESTTripersonal
E
3

This works:

find ./<SOURCE_DIR>/ -type d | sed 's/\.\/<SOURCE_DIR>//g' | xargs -I {} mkdir -p <DEST_DIR>"/{}"

Just replace SOURCE_DIR and DEST_DIR.

Eligible answered 4/6, 2015 at 14:20 Comment(0)
R
2

The following solution worked well for me in various environments:

sourceDir="some/directory"
targetDir="any/other/directory"

find "$sourceDir" -type d | sed -e "s?$sourceDir?$targetDir?" | xargs mkdir -p
Retroversion answered 22/7, 2013 at 16:7 Comment(0)
J
2

This solves even the problem with whitespaces:

In the original/source dir:

find . -type d -exec echo "'{}'" \; > dirs2.txt

then recreate it in the newly created dir:

mkdir -p <../<SOURCEDIR>/dirs2.txt
Jabiru answered 18/12, 2017 at 13:32 Comment(0)
D
2

Another tool that can do this: mtree

It first appeared on bsd systems, there are ports for linux too. In Ubuntu it is in package 'mtree-netbsd' or 'freebsd-utils'.

# 1: cd to your source dir
cd my_source_dir

# 2: create a specfile. Place the spec outside of the sourcedir and destdir
mtree -c > /tmp/myspec.txt

# 3: cd to the destdir
cd my_dest_dir

# 4: now create only the dir structure from the specfile
# -u  is for creating only dirs, it does not follow links
mtree -f /tmp/myspec.txt -u

If you later deleted some dirs in the destdir call the command form step 4 again, dir-structure will be restored.

mtree can do a lot more. follow links, create/delete specific files/dirs, delete or not delete files that are in the destdir...

Durr answered 15/6, 2023 at 7:14 Comment(0)
L
1

Substitute target_dir and source_dir with the appropriate values:

cd target_dir && (cd source_dir; find . -type d ! -name .) | xargs -i mkdir -p "{}"

Tested on OSX+Ubuntu.

Lodgings answered 31/8, 2012 at 23:59 Comment(0)
S
1
find source/ -type f  | rsync -a --exclude-from - source/ target/

Copy dir only with associated permission and ownership

Schizoid answered 8/6, 2020 at 19:50 Comment(0)
G
1
cd oldlocation
find . -type d -print0 | xargs -0 -I{} mkdir -p newlocation/{}

You can also create top directories only:

cd oldlocation
find . -maxdepth 1 -type d -print0 | xargs -0 -I{} mkdir -p newlocation/{}
Gurtner answered 26/9, 2021 at 10:25 Comment(1)
This solution works perfectly on LinuxMint 20.2, unlike the answer validated 10 years ago. Thank you!Taryntaryne
P
0

If you can get access from a Windows machine, you can use xcopy with /T and /E to copy just the folder structure (the /E includes empty folders)

http://ss64.com/nt/xcopy.html

[EDIT!]

This one uses rsync to recreate the directory structure but without the files. http://psung.blogspot.com/2008/05/copying-directory-trees-with-rsync.html

Might actually be better :)

Piscine answered 1/11, 2010 at 23:33 Comment(2)
Unfortunately, our CIFS-serving fileserver isn't running windows, so no can do on win commands.Miseno
Thank you, the rsync method worked perfectly fine for me. It's compatible with spaces in directory names as well.Selfdevotion
P
0

A python script from Sergiy Kolodyazhnyy posted on Copy only folders not files?:

#!/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)) 

or from the shell:

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

FYI:

Puzzler answered 8/8, 2017 at 23:13 Comment(0)
T
0

Another approach is use the tree which is pretty handy and navigating directory trees based on its strong options. There are options for directory only, exclude empty directories, exclude names with pattern, include only names with pattern, etc. Check out man tree

Advantage: you can edit or review the list, or if you do a lot of scripting and create a batch of empty directories frequently

Approach: create a list of directories using tree, use that list as an arguments input to mkdir

tree -dfi --noreport > some_dir_file.txt

-dfi lists only directories, prints full path for each name, makes tree not print the indentation lines,

--noreport Omits printing of the file and directory report at the end of the tree listing, just to make the output file not contain any fluff

Then go to the destination where you want the empty directories and execute

xargs mkdir < some_dir_file.txt
Tippett answered 13/5, 2019 at 20:14 Comment(0)
S
0

Simple way:

for i in `find . -type d`; do mkdir /home/exemplo/$i; done
Subjugate answered 22/6, 2021 at 21:48 Comment(0)
U
-1

Here is a solution in php that:

  • copies the directories (not recursively, only one level)
  • preserves permissions
  • unlike the rsync solution, is fast even with directories containing thousands of files as it does not even go into the folders
  • has no problems with spaces
  • should be easy to read and adjust

Create a file like syncDirs.php with this content:

<?php
foreach (new DirectoryIterator($argv[1]) as $f) {
    if($f->isDot() || !$f->isDir()) continue;
        mkdir($argv[2].'/'.$f->getFilename(), $f->getPerms());
        chown($argv[2].'/'.$f->getFilename(), $f->getOwner());
        chgrp($argv[2].'/'.$f->getFilename(), $f->getGroup());
}

Run it as user that has enough rights:

sudo php syncDirs.php /var/source /var/destination

Umbrella answered 25/7, 2018 at 18:2 Comment(1)
You don't have to like PHP and you don't have to use it. But the OP did not specify whether he wants a solution in any specific language and, like it or not, PHP is installed anyways on lots of Linux systems as 80% of the web uses PHP ( w3techs.com/technologies/details/pl-php/all/all ).Umbrella

© 2022 - 2024 — McMap. All rights reserved.