LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Linux - Newbie (https://www.linuxquestions.org/questions/linux-newbie-8/)
-   -   Backup adding numbers when using mv command (https://www.linuxquestions.org/questions/linux-newbie-8/backup-adding-numbers-when-using-mv-command-4175580571/)

kilee 05-24-2016 11:03 AM

Backup adding numbers when using mv command
 
Hello
I'm moving all zip files I have into a single folder with this:

find / -iname "*.zip" -type f -exec mv {} /Volumes/500/zip/ \;

Works perfect, but I'd like to make backups in case of name conflicts. -b looks like the answer, but the backups add a ~ symbol to the extension.

file.zip
file.zip~ and so on.

Is it possible to number the files before the extension?

file.zip
file1.zip
file2.zip

Thanks!

hazel 05-24-2016 11:28 AM

Yes, it is possible. You would need to write a script containing a for loop. I'm not quite sure of the syntax but it would be something like
Code:

number=1
for file in `find / -iname "*.zip" -type f`
do
mv $file `echo ${file%%".zip"}$number.zip`
number=$number+1
done

The echo command should strip the suffix off, insert a number, and put the suffix back on again.

dab1414 05-24-2016 11:29 AM

http://linux.die.net/man/1/mv

add "--backup=t" for numbered backups

EDIT: sorry this still puts number behind extension. "mv --suffix=.bak" will get rid of the ~

grail 05-24-2016 11:39 AM

You should not use a for loop if there is any possibility of word splitting occurring. Simply change to a while loop and you should be fine.

You also need to include some sort of test for the repeated file names as simply adding an ever increasing number will also give a numbered copy to something that only exists once.

HMW 05-24-2016 12:44 PM

^grail is right (as usual). A while loop is better:
Code:

#!/bin/bash

i=1
while read filename; do
    echo ${filename%%".zip"}$i.zip
    ((i++))
done < <(find . -iname "*.zip")

exit 0

Also:
Quote:

Originally Posted by grail
You also need to include some sort of test for the repeated file names as simply adding an ever increasing number will also give a numbered copy to something that only exists once.


syg00 05-24-2016 06:59 PM

Me, I'd just run over the final target dir and change the trailing tilde to say "_$(date +%F)".
KISS.

jpollard 05-26-2016 02:21 AM

Quote:

Originally Posted by HMW (Post 5550225)
^grail is right (as usual). A while loop is better:
Code:

#!/bin/bash

i=1
while read filename; do
    echo ${filename%%".zip"}$i.zip
    ((i++))
done < <(find . -iname "*.zip")

exit 0


:) I think it is cleaner as:
Code:

i=0
find . -iname "file*.zip" | while read filename; do
  ((i++))
done
if ((i)) ; then
    target=${file%%".zip"}$number.zip
else
    target=file.zip
fi

But then that is just me.

szboardstretcher 05-26-2016 03:31 AM

It should be mentioned that using 'mv' is ballsy because many many things can go wrong and cause you headaches. You shouldn't be using 'mv' unless you already have a backup, or don't care much about the data. Making a backup, copying files from one place to another, verifying, double-checking, and only then deleting, is a much more reliable route.

grail 05-26-2016 03:33 AM

@jpollard - I am not quite understanding your code? You are counting all the files that are duplicates and then seeing if positive you set a variable ... at what point are you going to do the copy/move?

JJJCR 05-26-2016 04:26 AM

Quote:

Originally Posted by szboardstretcher (Post 5551079)
It should be mentioned that using 'mv' is ballsy because many many things can go wrong and cause you headaches. You shouldn't be using 'mv' unless you already have a backup, or don't care much about the data. Making a backup, copying files from one place to another, verifying, double-checking, and only then deleting, is a much more reliable route.

Agree with this one, do an rsync to the destination folder once done then delete the source. Safer way. KISS method.

jpollard 05-26-2016 05:43 AM

Quote:

Originally Posted by grail (Post 5551080)
@jpollard - I am not quite understanding your code? You are counting all the files that are duplicates and then seeing if positive you set a variable ... at what point are you going to do the copy/move?

Afterwards. The snippit is more just to identify the possible name.

grail 05-26-2016 09:22 AM

ahhh .. cool .. I was just a bit lost :)

jpollard 05-26-2016 01:22 PM

Ran across another way... using shell array variables.

Instead of counting the list, if the list of names is put into an array you can get the size of the array...

keefaz 05-26-2016 04:15 PM

Yes or even better using a bash 4's hash
Code:

declare -A found
destdir=/Volumes/500/zip

find . -iname "file*.zip" | while read filename; do
  name=$(basename $filename)
  target=${name%%".zip"}${found["$name"]}.zip
  ((found["$name"]++))
  echo "mv $filename $destdir/$target"
done


jpollard 05-26-2016 05:03 PM

Quote:

Originally Posted by keefaz (Post 5551417)
Yes or even better using a bash 4's hash
Code:

declare -A found
destdir=/Volumes/500/zip

find . -iname "file*.zip" | while read filename; do
  name=$(basename $filename)
  target=${name%%".zip"}${found["$name"]}.zip
  ((found["$name"]++))
  echo "mv $filename $destdir/$target"
done


Well... that would work - depending on the total number of files. Using perl would be unbounded (since the hash can be a disk file instead of memory resident). Not sure about python, but I believe it can be unbounded as well.

But bash would have a memory limit...


All times are GMT -5. The time now is 03:09 AM.