'find -exec mv' misses 4 files

I wanted to move about 1000 mp3 files from a directory called ‘music’ containing a complicated nested directory structure, to a single directory called ‘mp3s’, so that I could listen to them in my car.

The command I used was:

find music -name '*mp3' -exec mv -v -t mp3s {} +

Something strange happened when I executed the command however. After the command finished, I noticed that four files had been omitted. These files were:

"music/Michael Hedges/Michael Hedges - Taproot/06 - Chava's Song.mp3"
'music/Michael Hedges/Michael Hedges - Aerial Boundaries/04 - Ragamuffin.mp3'
'music/Jonas Hellborg/1988 - Bass/07. Blues For LW.flac.mp3'
'music/Jonas Hellborg/1988 - Axis/03. Roman.flac.mp3'

I executed the exact same command again, and this time the four previously omitted files were moved as expected.

I cannot imagine why find might do something unexpected like this. Why might this have happened?

Executed into bash shell on Ubuntu.

Asked By: EmmaV

||

Hypothesis: name collisions

Imagine at some point the command was like:

mv -v -t mp3s … …/some_dir/foo.mp3 … …/another_dir/foo.mp3 …

foo.mp3 from some_dir was moved to mp3s, but foo.mp3 from another_dir triggered:

mv: will not overwrite just created 'mp3s/foo.mp3' with '…/another_dir/foo.mp3'

Apparently the message went unnoticed in the herd of messages caused by -v.

Later the second find tried to move …/another_dir/foo.mp3 again, but this time there was no …/some_dir/foo.mp3, so mp3s/foo.mp3 wasn’t considered "just created", it was overwritten.

Note -exec mv … {} + may run more than one mv. If …/some_dir/foo.mp3 and …/another_dir/foo.mp3 were assigned to different invocations of mv, the later mv would not consider mp3s/foo.mp3 as "just created". This means in your case there may have been more name collisions and some files were overwritten silently. Only name collisions where files with identical basenames were assigned to the same mv caused some files not to be moved.


Proof of concept

$ mv --version
mv (GNU coreutils) 8.30
Copyright (C) 2018 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <https://gnu.org/licenses/gpl.html>.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

Written by Mike Parker, David MacKenzie, and Jim Meyering.
$
$ mkdir -p music/a music/b music/c mp3s
$ touch music/a/A music/b/B music/c/A
$ tree --noreport
.
|-- mp3s
`-- music
    |-- a
    |   `-- A
    |-- b
    |   `-- B
    `-- c
        `-- A
$ find music -type f -exec mv -v -t mp3s {} +
renamed 'music/a/A' -> 'mp3s/A'
renamed 'music/b/B' -> 'mp3s/B'
mv: will not overwrite just-created 'mp3s/A' with 'music/c/A'
$ tree --noreport
.
|-- mp3s
|   |-- A
|   `-- B
`-- music
    |-- a
    |-- b
    `-- c
        `-- A
$ find music -type f -exec mv -v -t mp3s {} +
renamed 'music/c/A' -> 'mp3s/A'
$ tree --noreport
.
|-- mp3s
|   |-- A
|   `-- B
`-- music
    |-- a
    |-- b
    `-- c
$ 
Answered By: Kamil Maciorowski
Categories: Answers Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.