You can do this with GNU find and GNU mv:
find /dir1 -mindepth 2 -type f -exec mv -t /dir1 -i '{}' +
Basically, the way that works if that find goes through the entire directory tree and for each file (-type f) that is not in the top-level directory (-mindepth 2), it runs a mv to move it to the directory you want (-exec mv … +). The -t argument to mv lets you specify the destination directory first, which is needed because the + form of -exec puts all the source locations at the end of the command. The -i makes mv ask before overwriting any duplicates; you can substitute -f to overwrite them without asking (or -n to not ask or overwrite).
As Stephane Chazelas points out, the above only works with GNU tools (which are standard on Linux, but not most other systems). The following is somewhat slower (because it invokes mv multiple times) but much more universal:
find /dir1 -mindepth 2 -type f -exec mv -i '{}' /dir1 ';'
POSIXly, passing more than one argument, but using sh to reorder the list of arguments for mv so the target directory comes last:
LC_ALL=C find /dir1 -path '/dir1/*/*' -type f -exec sh -c '
exec mv "$@" /dir1' sh {} +
find . -type f -print0 | xargs -0 -I file mv --backup=numbered file .I also follow with another commandrename 's/((?:\..+)?)\.~(\d+)~$/_$2$1/' *.~*~to keep the numbering of duplicated files before the extension. – Paul Rougieux Sep 23 '21 at 12:20