Kelly
Kelly

Reputation: 649

mv Bash Shell Command (on Mac) overwriting files even with a -i?

I am flattening a directory of nested folders/picture files down to a single folder. I want to move all of the nested files up to the root level.

There are 3,381 files (no directories included in the count). I calculate this number using these two commands and subtracting the directory count (the second command):

find ./ | wc -l
find ./ -type d | wc -l

To flatten, I use this command:

find ./ -mindepth 2 -exec mv -i -v '{}' . \;

Problem is that when I get a count after running the flatten command, my count is off by 46. After going through the list of files before and after (I have a backup), I found that the mv command is overwriting files sometimes even though I'm using -i.

Here's details from the log for one of these files being overwritten...

.//Vacation/CIMG1075.JPG -> ./CIMG1075.JPG
..more log
..more log
..more log
.//dog pics/CIMG1075.JPG -> ./CIMG1075.JPG

So I can see that it is overwriting. I thought -i was supposed to stop this. I also tried a -n and got the same number. Note, I do have about 150 duplicate filenames. Was going to manually rename after I flattened everything I could.

Is it a timing issue? Is there a way to resolve?

NOTE: it is prompting me that some of the files are overwrites. On those prompts I just press Enter so as not to overwrite. In the case above, there is no prompt. It just overwrites.

Upvotes: 0

Views: 1476

Answers (2)

ShellFish
ShellFish

Reputation: 4551

Apparently the manual entry clearly states:

The -n and -v options are non-standard and their use in scripts is not recommended.

In other words, you should mimic the -n option yourself. To do that, just check if the file exists and act accordingly. In a shell script where the file is supplied as the first argument, this could be done as follows:

[ -f "${1##*/}" ]

The file, as first argument, contains directories which can be stripped using ##*/. Now simply execute the mv using ||, since we want to execute when the file doesn't exist.

[ -f "${1##*/}" ] || mv "$1" .

Using this, you can edit your find command as follows:

find ./ -mindepth 2 -exec bash -c '[ -f "${0##*/}" ] || mv "$0" .' '{}' \;

Note that we now use $0 because of the bash -c usage. It's first argument, $0, can't be the script name because we have no script. This means the argument order is shifted with respect to a usual shell script.

Upvotes: 2

Nick
Nick

Reputation: 10539

Why not check if file exists, prior move? Then you can leave the file where it is or you can rename it or do something else...

Test -f or, [] should do the trick?

I am on tablet and can not easyly include the source.

Upvotes: 1

Related Questions