Take the 2-minute tour ×
Ask Ubuntu is a question and answer site for Ubuntu users and developers. It's 100% free, no registration required.

Me again with another command-line script question :)

I made a helper script that looks like this

echo 'target.bak -> target.old_bak'
mv target.bak target.old_bak
echo 'target -> target.bak'
mv target target.bak
echo 'git clone:target -> target'
git clone ssh://Shark@mcs15:29418/our-trunk-target target
cd target
echo 'Managing hooks...'
scp -p -P 29418 Shark@mcs15:/hooks/commit-msg .git/hooks/
echo '... done. Enjoy the new clone while it lasts...'

This is pretty basic but it gets my point across - it keeps the last two clones and makes a new one, I need to retain my latest clone in the target folder because i symlinked my source folder in my eclipse project to point there :D

I would like to make an improvement to this script - instead of renaming target.bak -> target.old_bak and target -> target.bak I would like the following to happen:

if bakN exists then rename bakN -> bak(N+1)
rename recursivelly bak(N-1) -> bakN
rename target to target.bak
clone new repo into target

So in case I had gone through 6 clones and I'm cloning for the seventh time I'd like this to happen:

target.bak4 -> target.bak5
target.bak3 -> target.bak4
target.bak2 -> target.bak3
target.bak1 -> target.bak2
target.bak0 -> target.bak1
target      -> target.bak0
Cloning into 'target'... 

This community helped me immensely with my previous mass-diffing question so I hope you will be helpful enough to provide me with a decent way to do this one as well :)

EDIT:

The finalized script looks like this, thanks Wolfie for your major contributions.

#!/bin/bash
MYUSER="Shark"
TRUNK_FOLDER="target-on-trunk"
TARGET_FOLDER="target"

if [ -n "`ls -1d -v ${TARGET_FOLDER}.bak?`" ]; then
    echo "Pushing back numbered backups..."
    MAXBCK=`ls -1d ${TARGET_FOLDER}.bak* 2>/dev/null | egrep -o "[0-9]+$" | sort -n | tail -n1`
    if [ "$MAXBCK" != "" ]; then
        for (( c=$MAXBCK; c>=0; c-- ))
            do
                mv -v ${TARGET_FOLDER}.bak$c ${TARGET_FOLDER}.bak$(($c+1))
        done
    fi
fi

if [ -e "$TARGET_FOLDER.bak" ]; then
        mv -v ${TARGET_FOLDER}.bak ${TARGET_FOLDER}.bak0
fi

if [ -e "$TARGET_FOLDER" ]; then
        mv -v ${TARGET_FOLDER} ${TARGET_FOLDER}.bak
fi

echo "git clone: ${TRUNK_FOLDER} -> ${TARGET_FOLDER}"
git clone ssh://${MYUSER}@mcs15:29418/${TRUNK_FOLDER} ${TARGET_FOLDER}
cd ${TARGET_FOLDER}
echo 'Managing hooks...'
scp -p -P 29418 ${MYUSER}@mcs15:/hooks/commit-msg .git/hooks/
echo '... done. Enjoy the new clone while it lasts...'
share|improve this question
add comment

2 Answers

up vote 2 down vote accepted

This could help you:

For this files:

target.bak4 -> target.bak5
target.bak3 -> target.bak4
target.bak2 -> target.bak3
target.bak1 -> target.bak2
target.bak0 -> target.bak1

You can do this:

ls -1 target.bak* | awk '{print "mv "$0" "substr($0,0,length)substr($0,length,1)+1}' | sh

For target -> target.bak0 just do cp target target.bak

Update:

I tested this command and works only from 0 -> 19 backup, than the renaming fails... but for what you need is OK :)

Update #2:

Script version:

if [ $# != 1 ]; then
        echo 'Usage: $0 target'
        exit
fi
if [ `ls -1 $1* 2>/dev/null | grep -c $1` -lt 1 ]; then
        echo "No file found"
        exit
fi

MAXBCK=`ls -1 $1.bak* 2>/dev/null | egrep -o "[0-9]+$" | sort -n | tail -n1`

if [ "$MAXBCK" != "" ]; then
        for (( c=$MAXBCK; c>=0; c-- ))
        do
        #       echo $c $(($c+1))
                mv $1.bak$c $1.bak$(($c+1))
        done
fi

cp $1 $1.bak0

Example:

wolfy@wolfy-ubuntu:~/tmp$ ll
total 4
-rwxr-xr-x 1 wolfy wolfy 402 May 27 14:43 fresh_clone.sh*
-rw-r--r-- 1 wolfy wolfy   0 May 27 14:10 test
wolfy@wolfy-ubuntu:~/tmp$ ./fresh_clone.sh test
wolfy@wolfy-ubuntu:~/tmp$ ll
total 4
-rwxr-xr-x 1 wolfy wolfy 402 May 27 14:43 fresh_clone.sh*
-rw-r--r-- 1 wolfy wolfy   0 May 27 14:10 test
-rw-r--r-- 1 wolfy wolfy   0 May 27 14:44 test.bak0
wolfy@wolfy-ubuntu:~/tmp$ ./fresh_clone.sh test
wolfy@wolfy-ubuntu:~/tmp$ ll
total 4
-rwxr-xr-x 1 wolfy wolfy 402 May 27 14:43 fresh_clone.sh*
-rw-r--r-- 1 wolfy wolfy   0 May 27 14:10 test
-rw-r--r-- 1 wolfy wolfy   0 May 27 14:44 test.bak0
-rw-r--r-- 1 wolfy wolfy   0 May 27 14:44 test.bak1
wolfy@wolfy-ubuntu:~/tmp$ ./fresh_clone.sh test
wolfy@wolfy-ubuntu:~/tmp$ ll
total 4
-rwxr-xr-x 1 wolfy wolfy 402 May 27 14:43 fresh_clone.sh*
-rw-r--r-- 1 wolfy wolfy   0 May 27 14:10 test
-rw-r--r-- 1 wolfy wolfy   0 May 27 14:44 test.bak0
-rw-r--r-- 1 wolfy wolfy   0 May 27 14:44 test.bak1
-rw-r--r-- 1 wolfy wolfy   0 May 27 14:44 test.bak2

Try with this... but keep in mind that this is only a sample code, for "production" you should add some check before running this :)

This version works with N bak files... not only 19 ;)

share|improve this answer
    
how hard would it be to replace target with a $1 sortof argument? perhaps making it so that invoking it as fresh_clone.sh target would work too? –  Shark May 27 '13 at 10:20
    
I updated my answer –  Wolfy May 27 '13 at 11:28
    
ups, someting is wrong here... I will try to correct this :) –  Wolfy May 27 '13 at 11:38
    
I found out a few quirks which I'm ironing out as well. I will accept this as an answer and post my final version later :) Now I'm trying to make it somewhat more customizable, trying to define the user at the start. –  Shark May 27 '13 at 11:58
    
I added a script... again... this version is different from my firs command... –  Wolfy May 27 '13 at 12:16
show 2 more comments

I normally advise against using ls in a program (rationale here) but this seems straightforward, so:

touch target.bak{0..10}   # for testing

base=target
bak="${base}.bak"
command ls -vr "$bak"* | while IFS= read -r file; do
    n=${file#$bak}
    echo mv "$bak$n" "$bak$((n+1))"
done
echo mv "$base" "${bak}0"
mv target.bak10 target.bak11
mv target.bak9 target.bak10
mv target.bak8 target.bak9
mv target.bak7 target.bak8
mv target.bak6 target.bak7
mv target.bak5 target.bak6
mv target.bak4 target.bak5
mv target.bak3 target.bak4
mv target.bak2 target.bak3
mv target.bak1 target.bak2
mv target.bak0 target.bak1
mv target target.bak0

Notes:

  • use command to avoid any aliases or functions for ls
  • use ls's -v option to ensure files are sorted "numerically"
    • i.e., so "target.bak10" follows "target.bak9", not "target.bak1"
share|improve this answer
    
+1 for the -v option :) –  Wolfy May 27 '13 at 16:49
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.