mv -t
is a convenience provided by the GNU mv
command (the one you have on Linux). Other unix variants don't have that, you need to put the destination at the end. This does make it less convenient to use with xargs
or find … -exec
(which is why mv -t
was invented).
One way to put the arguments in the right order is to invoke a shell.
… | xargs sh -c 'mv "$@" "$0"' mysubdir
(mysubdir
is argument 0 to the shell; the arguments passed in batches by xargs
make up the positional parameters "$@"
.)
Beware that xargs
is not robust: it expects inputs in a peculiar quotes syntax. Your snippet breaks if you have file names containing whitespace or one of the characters \"'
. See Why does my shell script choke on whitespace or other special characters? for more information. To avoid problems with special characters in file names, use find … -exec …
:
find . -name . -o -type d -prune -o sh -c 'mv "$@" "$0"' mysubdir {} +
(-name . -o -type d -prune -o
skips subdirectories without recursing into them.)
For your use case of moving non-directories, if mysubdir
itself doesn't already contain subdirectories, it would be simpler to move all files, then move directories back:
mv * mysubdir/; mv mysubdir/*/ .
Alternatively, since you don't want to recurse into subdirectories, you could use a shell loop to enumerate files, and skip the ones that are directories.
for x in ./*; do
[ -d "$x" ] || mv "$x" mysubdir/
done
-a
, use-A
when you use-a
, may be you create loop , -a contains.
and..
and-A
doesn't contains them. – PersianGulf Feb 20 '15 at 13:02.
and..
are already excluded by thegrep
– Chris Davies Feb 20 '15 at 13:09