M BUZZ CRAZE NEWS
// general

Detecting if folder exists and renaming by pattern

By Joseph Russell

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...'

2 Answers

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 ;)

7

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"
0

Your Answer

Sign up or log in

Sign up using Google Sign up using Facebook Sign up using Email and Password

Post as a guest

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy