Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

Let's say I have as follows :

Folder A
    C1
        file a
    A2

Folder B
     C1
     B2
         file b
     B3

What I want is to merge these two folders, which would give me :

Folder C
    C1
    A2
    B2
    B3

Notice I didn't write file a and file b. I only want to merge the architecture. Each repository contains different files and I don't want them to be added to the merged directory. As a consequence, mv Folder\ A/* Folder\ B is not adequate.

Do you guys see a way to do so ?

share|improve this question
    
so you basically want to copy the directories but not the files in the directories? –  strugee Sep 5 '13 at 6:52
    
That's exactly my need. –  fxm Sep 5 '13 at 6:53
    
all right, here's my lazy answer: mkdir dir3 && cp -r dir1/* dir3/ && cp -r dir2/* dir3/, then use find to go through and find any regular files and delete them. –  strugee Sep 5 '13 at 6:56
2  
@strugee; Expensive. Use cp -rl to hardlink, then it's cheaper. –  M.E.L. Sep 5 '13 at 8:00

3 Answers 3

up vote 7 down vote accepted

Well, you could have find exec mkdir.

cd /A/
find -type d -exec mkdir -p /C/{} \;

Or if the structure is flat as shown in your example, without find

cd /A/
for dir in */
do
    mkdir -p /C/"$dir"
done

and in both cases the same again for cd /B/.

share|improve this answer
    
I tried your first solution (structure is not flat), but I'm affraid I can't find the folder C. Where is it supposed to go ? –  fxm Sep 5 '13 at 8:50
    
@fxm: He's just abbreviating your folder names. Where he says A, he means the same thing you named as Folder A. So, C is Folder C. File names with spaces in them require careful attention to quoting, so it's simpler to give a correct example this way. –  Warren Young Sep 5 '13 at 9:12
    
Also note it needs either absolute paths or paths relative to /A/ or /B/, e.g. ../C/ instead of C/. I assumed A B C was an example and you know how to specify the location of the real directories. –  frostschutz Sep 5 '13 at 9:15
    
I realize it, but changing /C/ by ~/newFolder/ doesn't seems to create the afroementionned folder in my home –  fxm Sep 5 '13 at 9:21
    
Oh, sorry, my bad. Use \; instead of +. –  frostschutz Sep 5 '13 at 9:29

If you just want to create the same directory structure, you can call find to traverse each existing directory tree and call mkdir with the right argument on each subdirectory. Call mkdir -p to silently skip directories that already exist.

cd 'Folder A'
find . -type d -exec mkdir -p '/path/to/Folder C/{} '\;
cd 'Folder B'
find . -type d -exec mkdir -p '/path/to/Folder C/{} '\;

In zsh, assuming that Folder A, Folder B and Folder C are subdirectories of the same directory:

mkdir -p Folder\ [AB]/**/*(/e\''REPLY=Folder\ C/${REPLY#*/}'\')

If you want to reproduce the directory hierarchy with file permissions, you can call rsync, and give it a filter that only includes the directories and not the regular files. Make sure to include a / at the end of the source directories so that their content is copied directly under /path/to/Folder C without creating /path/to/Folder C/path/to/Folder A and so on.

rsync -a --include='*/' --exclude='*' '/path/to/Folder A/' '/path/to/Folder B/' '/path/to/Folder C'
share|improve this answer

Here's how I would do it:

$ (find "Folder A"/* -type d ; find "Folder B"/* -type d) | \
           sed 's#[^/]\+/##' | xargs -I{} mkdir -p "Folder C"/{}

Details

This will generate the list of sub-directories under "Folder A" and Folder B", that list will look like this:

Folder A/A2
Folder A/C1
Folder B/B2
Folder B/B3
Folder B/C1

Piping that output through this sed command will remove the "Folder .." bit:

sed 's#[^/]\+/##'

Resulting in this:

A2
C1
B2
B3
C1

NOTE: The above sed is looking from the left side, finding everything that is not a slash, up to the first slash, these characters are then substituted with nothing, essentially deleting them.

At this point you just need to mkdir under the "Folder C" directory, so we'll use xargs to do this repetitive task:

xargs -I{} mkdir -p "Folder C"/{}

This says to take each argument in as {} and substitute it into the following command ever where there's a corresponding {}.

Example

Sample data:

$ tree Folder\ {A,B,C}
Folder A
|-- A2
`-- C1
    `-- filea
Folder B
|-- B2
|   `-- fileb
|-- B3
`-- C1
Folder C

NOTE: See "Folder C" is empty to start.

Now we run our command:

$ (find "Folder A"/* -type d ; find "Folder B"/* -type d) | \
           sed 's#[^/]\+/##' | xargs -I{} mkdir -p "Folder C"/{}

And we're left with the following:

$ tree Folder\ C
Folder C
|-- A2
|-- B2
|-- B3
`-- C1
share|improve this answer
    
How about find A/ B/ -type d -print0 | sed -z ... | xargs -0 ...? –  frostschutz Sep 5 '13 at 17:52

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.