Celeb Glow
updates | March 18, 2026

How to copy files while keeping directory structure?

This is for a java project, but the same concept can be applied more generally:

Basically, I have a projects with all *.java files located in some sub directory of src. Now I want to grab all directories with the name test in that directory tree and move them into a new directory called tests, e.g.:

src->com->a1 -> A.java -> B.java -> test -> test1.java -> test2.java

to

src->com->a1 -> A.java -> B.java
tests->com->a1->test -> test1.java -> test2.java

How would I best do that?

5

3 Answers

You'll need to write a shell script for this task. I'll give it a try and comment the lines.

The first line here is just a variable where you put the absolute directory of your src tree.

SRCDIR=/dir/where/src/lives

The next line executes find. The command will put every directory path with the name test into the variable TESTDIRS.

TESTDIRS=$(find $SRCDIR -type d -name test)

Now you iterate over all found test directories

for dir in $TESTDIRS; do

This takes the actual path and removes everything including src. So you get the structure for creating the new path.

 NEWDIR=${dir##*/src}

Now create the new directories.

 mkdir -p tests/$NEWDIR

Move the old test directory to the newly created place.

 mv $dir tests/$NEWDIR

end the iteration

done

As far as I understand you this should what you want. But please test it first. There might be some caveats and running the script as is might lead to data loss.

Please note that the meanings of move mv and copy cp are distinct and well defined for terminal usage. mv means that the files will no longer exist in the old location, while cp means that a duplicate is made in the new location.

Simple solution (notice that I use mv, but you may want to use cp first and then remove the old files once the copying is what you want):

cp src/com/a1/test/test*.java tests/com/a1/test/

More elegant solution (this one moves the files, not copies):

cd src/com/
find . -iname "test*.java" -type d -exec mv {} ../../tests/com/ \;

If the second solution doesn't work for your specific test case, we can iterate...

2

I use one these commands to copy all my jpg files and skip all the db, raw etc files. Either one should work for your needs.

Using rsync:

 rsync -a --prune-empty-dirs --include '*/' --include '*.jps' --exclude '*' source/ target/

Or find with exec:

find . -name '*.jpg' -exec cp --parents \{\} /target \;

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