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

From: Petr Malat <[email-masked]>
Date: Tue, 5 Mar 2024 00:16:36 +0100

On Mon, Mar 04, 2024 at 08:35:03PM +0000, P??draig Brady wrote:
> On 04/03/2024 15:47, P??draig Brady wrote:
> > 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.
> > 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 do not think this would be ever needed in a real life. It's more likely
one actually wants something like this:
  mkdir d.tmp
  ln -s -t d.tmp d/*
  # Modify d.tmp as needed (without propagating changes to d)
  mv --swap d d.tmp

> > I will look at making the change before the upcoming release.
> 
> Another point worth mentioning before changing this,
> is that changing would make the --swap operation non symmetric.
> I.e. `mv -x a d` would be different to `mv -x d a` where d in a directory.
I think this would lead to bugs. I prefer KISS principle and allowing
swapping just 2 paths. Explicitly mentioning -x automatically implies
-t may be added to the documentation. In general, I do not think there
is any need to make mv -x behave similar to plain mv. It's normal an
option changes behavior, at the end -t does the same.

> p.s. Re dir swapping I noticed that specifying '/' or '.' dirs always gives EBUSY:
>   $ mv -x . .
>   mv: swap of '.' and '.' failed: Device or resource busy
That's because it's CWD of mv and your shell.
  Petr