Hi Mikhail and Samuel,

Samuel Thibault <[email protected]> said:

> Mikhail Karpov, le mar. 08 sept. 2026 12:00:06 +0700, a ecrit:
> > If you try to rename a file with the -n flag while keeping the same name, mv
> > reports that no replacement occurred in GNU/Linux, while mv reports nothing
> > in GNU/Hurd:
> > 
> > user@user:~$ > file
> > user@user:~$ stat file
> >   File: file
> >   Size: 0             Blocks: 0          IO Block: 4096   regular empty file
> > Device: 259,2    Inode: 10131664    Links: 1
> > Access: (0664/-rw-rw-r--)  Uid: ( 1000/    user)   Gid: ( 1000/ user)
> > Access: 2026-09-08 10:58:30.443730136 +0700
> > Modify: 2026-09-08 10:58:30.443730136 +0700
> > Change: 2026-09-08 10:58:30.443730136 +0700
> >  Birth: 2026-09-08 10:58:30.443730136 +0700
> > user@user:~$
> > user@user:~$ mv -n file file
> > mv: not replacing 'file'
> 
> I am not getting this error on linux:
> 
> € mv -n blip blip
> €
> 
> (and stat doesn't change either)
> 
> > Since the file's stat doesn't change, I assume mv isn't performing any
> > manipulations on the file and simply doesn't report that no replacement
> > occurred.  As far as I can tell, this is because the copy_internal function
> > from coreutils/src/copy.c handles this error differently.
> > 
> > Is this behavior desirable?
> 
> That would probably have to be discussed with coreutils people :)

I wasn't involved in this change, but I hope I am qualified enough. :)

In coreutils-9.2 the behavior was changed to be compatible with FreeBSD
following a bug report [1]. Here is the FreeBSD behavior:

    $ touch a b; cp -n a b; echo $?
    1

Here is the coreutils-9.1 behavior:

    $ cp --version | head -n 1; touch a b; cp -n a b; echo $?
    cp (GNU coreutils) 9.1
    0

Here is the coreutils-9.2 behavior:

    $ cp-9.2 --version | head -n 1; touch a b; cp-9.2 -n a b; echo $?
    cp (GNU coreutils) 9.2
    1

Surprisingly, this caused some issues with users, especially
distributions. The length of the discussion in the bug reports should
give you a decent idea, without needing to read the entire thing [2]
[3]. Debian ended up adding a warning when the option was used in a
patch, if I understand correctly.

During discussion with distributions a warning was added in
coreutils-9.3. Here is the coreutils-9.3 behavior:

    $ cp-9.3 --version | head -n 1; touch a b; cp-9.3 -n a b; echo $?
    cp (GNU coreutils) 9.3
    cp-9.3: not replacing 'b'
    1

Eventually, the behavior was reverted to be the same as coreutils-9.1 in
coreutils-9.5. See the following NEWS entry:

    cp --no-clobber, and mv -n no longer exit with failure status if
    existing files are encountered in the destination.  Instead they revert
    to the behavior from before v9.2, silently skipping existing files.

It has not been changed since then:

    $ cp --version | head -n 1; touch a b; cp -n a b; echo $?
    cp (GNU coreutils) 9.11.252-aea70
    0

coreutils-9.5 also added 'cp --update=none-fail', to compliment 'cp
--update=none' added in coreutils-9.3, allowing for both behaviors
without the portability issues of 'cp -n':

    $ cp --version | head -n 1; touch a b; 
    cp (GNU coreutils) 9.11.252-aea70
    $ cp --update=none a b; echo $?
    0
    $ cp --update=none-fail a b; echo $?
    cp: not replacing 'b'
    1

So, I suspect this is related to what versions you are using and how
they are patched.

Collin

[1] https://bugs.gnu.org/61105
[2] https://bugs.gnu.org/62572
[3] https://bugs-devel.debian.org/cgi-bin/bugreport.cgi?bug=1058752

Reply via email to