Tux

...making Linux just a little more fun!

[2-cent Tip]: Renumbering files

Ben Okopnik [ben at linuxgazette.net]


Wed, 18 Aug 2010 20:01:52 -0400

This comes up occasionally: you have a numbered list of files and you need to reorganize them, say by moving all the numbers up two places to accomodate two more files being added to the "front of the queue", or inserted in the middle of it. Even if you're familiar with loops, the answers aren't quite as simple as "loop over the numbers, add 2, and rename": doing so would overwrite the third file with the first one, the fourth one with the second one, and so on. Ugh, what a mess!

Here's the general form of an approach that'll work well:

start=0		# Lowest number in the list
end=10		# Highest number in the list
incr=2		# The increment
for n in $(seq $start $end|tac); do mv $n $(($n + $incr)); done

Since piping the list through 'tac' will invert it, we will now be renaming the files in reverse order - that is, 10->12, 9->11, 8->10, and so on - which will prevent the above collisions. Renaming files that have numbers as part of the name isn't much more difficult: given, say, 'File1xyz.txt' and so on, the loop body simply becomes

for n in $(seq $start $end|tac)
do
	mv File${n}xyz.txt File$(($n + $incr))xyz.txt
done

Bonus feature: if you have a list of numbers that goes over 9 (or 99), and you want it sorted numerically (rather than '1 10 11 12 2 3 ...'), just use 'printf' to format the second parameter:

for n in $(seq $start $end|tac)
do
    mv $n $(printf '%02d' $(($n + $incr)))
done

The '02' in the above will result in numbers that are always 2 digits long, by prefixing the single-digit ones with a zero. Obviously, this can be extended to whatever number of digits is desired - and 'ls' will now show a properly numerically-sorted list.

-- 
* Ben Okopnik * Editor-in-Chief, Linux Gazette * http://LinuxGazette.NET *


Top    Back


Neil Youngman [ny at youngman.org.uk]


Thu, 19 Aug 2010 10:05:33 +0100

On Thursday 19 August 2010 01:01:52 Ben Okopnik wrote:

> ```
> start=0?????????# Lowest number in the list
> end=10??????????# Highest number in the list
> incr=2??????????# The increment
> for n in $(seq $start $end|tac); do mv $n $(($n + $incr)); done
> '''
>
> Since piping the list through 'tac' will invert it, we will now be
> renaming the files in reverse order - that is, 10->12, 9->11, 8->10,
> and so on - which will prevent the above collisions.

Nice, but the pipe to 'tac' isn't really necessary '$(seq $end -1 $start)' will do just as well.

Neil


Top    Back


Ben Okopnik [ben at linuxgazette.net]


Thu, 19 Aug 2010 08:58:50 -0400

On Thu, Aug 19, 2010 at 10:05:33AM +0100, Neil Youngman wrote:

> On Thursday 19 August 2010 01:01:52 Ben Okopnik wrote:
> > ```
> > start=0?????????# Lowest number in the list
> > end=10??????????# Highest number in the list
> > incr=2??????????# The increment
> > for n in $(seq $start $end|tac); do mv $n $(($n + $incr)); done
> > '''
> >
> > Since piping the list through 'tac' will invert it, we will now be
> > renaming the files in reverse order - that is, 10->12, 9->11, 8->10,
> > and so on - which will prevent the above collisions.
> 
> Nice, but the pipe to 'tac' isn't really necessary '$(seq $end -1 $start)' 
> will do just as well.

Oh, cool - I've been usng 'seq' for years, and didn't know it could do that. Thanks!

-- 
* Ben Okopnik * Editor-in-Chief, Linux Gazette * http://LinuxGazette.NET *


Top    Back