I have a batch of files all ending with the same string, ie: *_ext.dat located in several sub-dirs along with several other files, in a given main dir. This is the structure:




I need to recursively move only the files ending in *_ext.dat into a new main dir, new_dir, respecting the sub-dir structure so the files will end up in an equivalent dir structure like this:




Because of this the command should also create those sub-dirs with their corresponding names. I know that with a line like this one:

find . -name "*_ext.dat" -print0 | xargs -0 rm -rf

I can delete all those files, but I don't know how to modify it to do what I need (or if it is even possible).

  • 1
    Probably somthing like rsync --include=*_ext.dat /main_dir/ /new_dir/ will do the trick. Haven't tested it though. – Jaap Eldering Oct 9 '13 at 0:24

I would first create the subdirectories in new_dir by

cd main_dir
for i in *; do mkdir "../new_dir/$i"; done
cd ..

Then you can use bash's for command again along with pattern expansion to do exactly what you need quickly:

for i in main_dir/*/*_ext.dat; do cp "$i" "new_dir${i##main_dir}"; done

using the fact that the destination directories exist. Finally, if were not guaranteed that each of them would actually be used, you can purge the empty ones afterwards:

cd new_dir
rmdir --ignore-fail-on-non-empty *
  • In the first loop you are expecting that in the main_dir there are only directories. Also you are not double-quoting the paths in all your code so it will not work with file names containing spaces. This code will be much more robust: for i in */; do mkdir "../new_dir/$i"; done. --- The last piece of code will not remove directories containing empty directories. For that you can use find: How do you remove nested empty directories using a Bash script on Linux? – pabouk Nov 11 '13 at 7:59
  • @pabouk Of course it will. (Perhaps you didn't notice the cd preceding it?) Man page of rmdir says: "DESCRIPTION ... Remove the DIRECTORY(ies), if they are empty." The option --ignore-fail-on-non-empty opts out from the warnings that non-empty directories were left out. Moreover, I tried it on my system before posting. – The Vee Nov 11 '13 at 11:04
  • Also, the directory structure my commands expect agrees perfectly with the way the OP introduced it including his explicit examples. Of course the commands would be different if the structure was. – The Vee Nov 11 '13 at 11:05
  • Thanks, though, for the comment on spaces. Fixed. – The Vee Nov 11 '13 at 11:08
  • You are welcome. You exaggerated with the double quotes. The last command will not do what you want. --- First loop: Is not it better to add single / so that the code is more universal and works in more use-cases? --- Last command does not work: mkdir a ; cd a ; mkdir -p a/b/c d/e/f g/h/i ; ls ; rmdir --ignore-fail-on-non-empty * ; ls --- output: a d g a d g – pabouk Nov 11 '13 at 11:20

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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