I am trying to copy files and the directory it is in to another location. I can find the path like this:

find ~/dim_import/* -type f ! -name xdir | cut -d '/' -f 5-10

which outputs


How do I copy these to another location? For example the new location would be


The issue is that there are more directories that are empty and I do not want to copy those, only the directories that have files in them and the files themselves.

NOTE: not using bash, using sh.


4 Answers 4


Here is a method that only uses POSIX shell features:

find ~/dim_import/* -type f ! -name xdir -exec sh -c '
  mkdir -p new/"$d"; 
  cp "$1" new/"$d"' -- {} \;
  • This fails. It outputs: cp: cannot access : No such file or directory cp: cannot access : No such file or directory cp: cannot access : No such file or directory So the mkdir command isn't working
    – James
    Commented Jul 13, 2015 at 13:46
  • I'm think the problem here is that you need to use 0 for every 1 ised in the answer ($0 in ash -c command is equivalent to $1 in a shell script. I have no idea why that's the case).
    – evilsoup
    Commented Jul 15, 2015 at 16:59
  • @evilsoup in this case, $0 is --.
    – jordanm
    Commented Jul 15, 2015 at 18:01

xargs should be available. You could use:

find ~/dim_import/* -type f ! -name xdir | xargs -I {} cp {} new/{}
  • This will copy to new/$HOME/dim_import/general/ and will only work if that path already exists. He just wants new/general.
    – jordanm
    Commented Jul 10, 2015 at 21:17

Since you already know how to filter the files, then use recursive copy: cp -R

Or you could just use rsync with --prune-empty-dirs option.

rsync --exclude='*xdir*' --prune-empty-dirs ~/dim_import ~/new

Note: If you don't use trailing slash from source (like above's example) dim_import is also copied.

  • I tried recursive copy, doesn't work how I want it.
    – James
    Commented Jul 13, 2015 at 12:45

I ended up just writing to a file:

find ~/dim_import/* -type f ! -name xdir | cut -d '/' -f 5-6 > files

and then looping through the "files" file and creating the directories from that and then copying the files there.

while read line; do
  fileDir=`echo "$line" | cut -d '/' -f 1`    # get folder name
  fileName=`echo "$line" | cut -d '/' -f 2`   # get file name
  cd ~/"sr${srNum}"                           # go to SR folder

  # If proper directory doesn't exist, create
  if [ ! -d "$fileDir" ]; then 
    mkdir "$fileDir"

  # Copy file to respected directory
  cd $ROOT                                        # go back to dim_import
  cp "$fileDir/$fileName" ~/"sr$srNum/$fileDir"   # copy file to fileDir folder
  cd ~/"sr$srNum/$fileDir"                        # go to fileDir
  chmod u+w "$fileName"                  # mod the file for write access for changes
  cd $ROOT                                        # go back to dim_import
done < files

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .