Subject: bug#69532: mv's new -x option should be made orthogonal to -t/-T/default

From: Dominique Martinet <[email-masked]>
Date: Tue, 5 Mar 2024 09:43:56 +0900

Adding Rob to the loop because this impacts compatibility with
toybox/maybe busybox implementations
(Quoting in full for convenience, there's a few more mails in
https://lists.nongnu.org/archive/html/bug-coreutils/2024-03/msg00002.html
but we seem to be missing Petr's reply)

Pádraig Brady wrote on Mon, Mar 04, 2024 at 03:47:23PM +0000:
> On 04/03/2024 00:44, Paul Eggert wrote:
> > Although I like the idea of exposing file swaps to the user, the first
> > cut of 'mv -x' has significant problems.
> > 
> > I expect 'mv -x A B' to act like 'mv A B' except the destination must
> > exist and is renamed back to A. However, this is not true for 'mv -x A
> > B' when B is a directory; it renames B to A rather than renaming B/A to
> > A as I expect. That is, 'mv -x' acts as if -T (--no-target-directory) is
> > also specified. There is no way to get mv's traditional behavior, or to
> > get mv -t behavior.
> > 
> > To fix this, 'mv -x' should respect the usual mv behavior with respect
> > to directories. For example, when D is a directory 'mv -x A B C D'
> > should act like 'mv A B C D' except that D's old entries should be
> > renamed back to A B and C. And the -t and -T options should work with -x
> > the same way they work when -x is not specified.
> > 
> > This needs to happen before the next coreutils release, to avoid
> > confusion about 'mv -x'.
> 
> So you're saying the current mv -x behavior should only be with -T explicitly specified.
> With the current implementation, we should at least document that -x implies -T.
> 
> By changing as you suggest, we'd not be adding any significant functionality,
> but potentially reducing confusion by following mv traditional arg handling.
> I agree with you I think, but not strongly.
> 
> It's worth stating though that if users want to swap 2 directories
> they'd have to `mv -Tx d1 d2`, which may also be a little confusing.
> 
> The use case we don't currently support directly is:
> cd source_dir && mv -x * "$dest_dir"
> Instead that currently requires:
> for f in *; do mv -x "$f" "$dest_dir"; done
> 
> For completeness, stating disadvantages of pulling this use case within mv,
> is that by requiring the for loop for this would allow users
> to programatically determine which swap failed, and I see --swap
> as primarily a programatic interface used by scripts.

I also see --swap mostly used by scripts and this actually feels a bit
dangerous to me -- I'd *always* use this with -T.
The point of --swap is that it's safe to use concurrently or when
something else might happen in parallel, but if you behave differently
when something else places a directory that'll likely lead to weird
script failures at some point.

I also find it a bit weird that `mv --swap a b` is different from `mv
--swap b a` -- this is normal for mv without --swap, but swap kinds of
changes my expectation of mv...
I agree with Petr's reply that operating on arguments directly is
simpler to reason about, especially in the context of scripts.

(by the way, what's this "rename" command you speak of? I know of a few
different implementations that often get placed as "rename" in $PATH but
I'm not aware of any such command that'd be installed on most systems)

> Also if we made this change, We'd have to document that `mv -x 1 2 ... d`
> was not atomic over the whole set.
> 
> I will look at making the change before the upcoming release.

Thanks,
-- 
Dominique Martinet | Asmadeus