Maintain directory structure copying `find` results

Let’s say you have a directory structure consisting of files owned by various users, but you want to copy only the files of a particular user to another path, but maintain the directory structure in the destination path. If you just use something like this…

find /path/to/src/ -user foo -exec cp -a {} /path/to/dst/

…you end up with all of the files in /path/to/dst/ with the original directory structure flattened out.

I came up with the following to solve the problem:

find /path/to/src/ -user foo | while read FILE \
do \
    DIR=$( dirname ${FILE} ); \
    mkdir -p /path/to/dst/${DIR}; \
    cp -d --preserve=mode,ownership,timestamp ${FILE} /path/to/dst/${DIR}; \
done

Here’s a brief explanation. Since the find command returns the relative path of the matching item in it’s STDOUT, we can use the dirname command to get the original relative directory name. We then create the directory if it doesn’t exist, and finally do the copy.

  1. [...] I needed to remove messages older than a week old for a list of email accounts on a Plesk system running Qmail. I put together the following BASH script to locate the messages using find and back them up outside of the mailbox (just in case). This builds on the technique I used in my previous post, Maintain directory structure copying `find` results. [...]

Leave a Reply