Search code examples
bashunixmkdirmv

Finding and moving all files while keeping directories intact


read source
read destination 
destination=$(cd -- "$destination" && pwd)
cd -- "$source" &&
  find . -name '*.ext1' -o -name '*.ext2' -exec sh -c '
    mkdir -p "$0/${1%/*}"
    mv "$1" "$0/$1"
  ' "$destination" {} \;

I have the above code which finds files and then tries to preserve the directory structure. But the issue is it doesn't find and move all files over of the type I requested - what's wrong? It seems to miss files that aren't in the lowest directory level.

Source/
\->File (misses this)
\->Folder/
   \->File (finds/moves this)

Solution

  • -o has lower precedence than the implied -a between adjacent expressions, and so

    find . -name '*.ext1' -o -name '*.ext2' -exec blah

    will be parsed as

    find . '(' -name '*.ext1' ')' -o '(' -name '*.ext2' -exec blah ')'.

    To get what you want, do:

    find . '(' -name '*.ext1' -o -name '*.ext2' ')' -exec sh -c '
      mkdir -p "$0/${1%/*}"
      mv "$1" "$0/$1"
    ' "$destination" {} \;