Here's a more paranoid script that avoids all usernames (uses "@@@" for the tmp dir), preserves the dotfiles that the "mv $a/homedir/*" discards, stops if the @@@ dir isn't consistent, and shouldn't have a command length problem. The remaining weakness is pathological user names.
cd /home
ls -1 | while read user ; do # allow many user dirs without imploding
[ -d @@@ ] && { echo tmp already present, aborting 1>&2 ; exit 1 ; }
mv $user @@@
mv @@@/homedir $user
rmdir @@@ || { echo tmp dir for $user not empty, aborting 1>&2 ; exit 2 ; }
done
The find() approach is a good choice if the entire per-directory command were buried in the -exec, as in:
cd /home && find -name . -o -type d -prune -print \
-exec mv '{}' @@@ ';' \
-exec mv @@@/homedir '{}' ';' \
-exec rmdir @@@ ';'
Trying something like "for f in $(find ....)"
is fragile, since shells will want to expand that entire command line first. The finds shown here depend on {} being expanded by find even within strings, which I'm not sure all finds support.
or even
cd /home && find -name . -o -type d -prune -print -exec \
sh -c 'mv {} @@@ && mv @@@/homedir {} && rmdir @@@' ';'
Testing:
mkdir -p {fred,jan,alice}/homedir
touch {fred,jan,alice}/homedir/.dotstuff
touch {fred,jan,alice}/homedir/stuff
The let one rip (minus the "cd /home") and see how it does. All seem to work well here.