home/*
and *
are shell globs, they are first expanded by the shell (so here running as yourself, not with superuser privileges), and the resulting words are then passed as argument to the command.
So if home
contains .
, ..
, .hidden
. u1
, u2
and the current directory contains .
, ..
, .hidden
, -i
, x
, y
, the arguments that mv
will receive are mv
, home/u1
, home/u2
, -i
, x
, y
.
Some implementations of mv
like GNU mv
have that misfeature that arguments starting with -
are still recognised as options even if they occur after non-option arguments, so above that -i
would be taken as a -i
option to mv
(sudo
doesn't have that misfeature for obvious reasons).
y
would be taken by mv
as the destination directory, and that's where the files would disappear to if y
was of type directory (or symlink to directory).
mv
will not see a *
or home/*
argument (unless there are files actually named like that there of course). However note that some shells like most Bourne-like ones have that misfeature that if the glob doesn't match any file, it is passed as is (unexpanded) to the command.
So, with those, if the current directory only contains hidden files, then mv
would receive *
as the last argument. mv
doesn't treat *
specially (it's the shell's role to understand globs), so will treat it as the literal name of the target directory. Now, if there's no non-hidden file, that directory *
won't exist either, so mv home/u1 home/u2 *
would just report an error about the target directory not existing. If there was only u1
in home
though, mv home/u1 *
would make mv
rename home/u1
to *
in the current directory.
That misfeature was introduced by the Bourne shell in 1979. In earlier Unix versions (and in csh which didn't change it), the command is cancelled if none of the globs match. globs were then expanded by a /etc/glob
helper (which gave their name to globs). If at least one glob matched any file though, the non-matching globs were removed. So in csh/tcsh (or zsh -o cshnullglob
) a mv home/* *
where the current directory has no non-hidden file would become mv home/u1 home/u2
which would move u1
into u2
.
Modern shells like zsh
or fish
(or bash -o failglob
) have fixed it by cancelling the command if any of the globs don't match.
*
expands to all the files in the current directory (excluding.
and..
) - you can see this by runningecho *
. See this page documenting globs mywiki.wooledge.org/glob#extglob and the slightly more cryptic section of the reference manualecho *
only prints*
in my computer. I tried withecho -e *
too.