Find – How to Move or Copy All Files to a Directory with the Same Filename Prefix

directory-structurefile-copyfilenamesfind

Using Bash

So let's say I have a bunch of files randomly placed in a parent directory ~/src, I want to grab all the files matching a certain suffix and move (or copy) them to a ~/dist directory.

Let's assume for this purpose that all filenames have this naming convention:

<filename_prefix>.<filename_suffix>

I found out that this was a quick way to get all files with a particular filename_suffix and put them in a dist folder:

mkdir ~/dst
find source -name "*.xxx" -exec mv -i {} -t ~/dst \;

Now a step further… how can I use the output of find, in this case filename, and use the filename_prefix to generate a directory of the same name in ~/dist and then move (or copy) all the files with that prefix into the appropriate directory?

mkdir ~/dst
find source -name "*.xrt,*.ini,*.moo" -exec mv -i {} -t ~/dst \;

Essentially, how do I change the above command (or maybe use another command), to create a structure like this

(OUTPUT)

~/dist/people/people.xrt
~/dist/games/games.xrt
~/dist/games/games.moo
~/dist/games/games.ini
~/dist/monkeys/monkeys.ini
~/dist/monkeys/monkeys.xrt

from a directory tree like this?

(INPUT)

~/src/xrt/people.xrt
~/src/xrt/games.xrt
~/src/conf/games.ini
~/src/pack/monkeys.xrt
~/src/e344/games.moo
~/src/e344/monkeys.moo
~/src/en-us/monkeys.ini

Best Answer

It would be a hell to tell find what to do in this case.

Better use the shell:

for i in **/*.{xrt,ini,moo}; do
  FILE=$(basename "$i")
  DIR=~/dst/${FILE%.*}
  echo mkdir -p -- "$DIR"
  echo mv -i -t "$DIR" -- "$i"
done

Use shopt -s globstar to make the ** glob work (or use zsh!). And remove the echos later if the command prints what you want.

Related Question