Sometimes in the recovery of Oracle databases, it is necessary to apply a series of log files with numeric sequences in their filenames:

SVRMGR> recover database until time '2009-08-09:18:00:00' using backup controlfile;
ORA-00279: Change 6827248660254 generated at 08/07/09 16:36:11 needed for thread 1
ORA-00289: Suggestion : /home/oracle/oracle/arch/arch.log1_253737.dbf
ORA-00280: Change 6827248660254 for thread 1 is in sequence #253737
Specify log: {=suggested | filename | AUTO | CANCEL}
cancel
Media recovery cancelled.

In this case a sequence starting with arch.log1_253737.dbf, and ending with the log produced immediately following the chosen point in time of recovery.

However, let us presume that these logs are all compressed, and they include many that are not needed for the recovery session. We only want to decompress logs that will be used:

$ ll arch.log1_25373*
-rw-rw---- 1 oracle dba 7388322 Aug  7 06:15 arch.log1_253730.dbf.bz2
-rw-rw---- 1 oracle dba 7229983 Aug  7 08:03 arch.log1_253731.dbf.bz2
-rw-rw---- 1 oracle dba 8311763 Aug  7 10:01 arch.log1_253732.dbf.bz2
-rw-rw---- 1 oracle dba 8071537 Aug  7 12:01 arch.log1_253733.dbf.bz2
-rw-rw---- 1 oracle dba 8275022 Aug  7 14:01 arch.log1_253734.dbf.bz2
-rw-rw---- 1 oracle dba 8209028 Aug  7 15:59 arch.log1_253735.dbf.bz2
-rw-rw---- 1 oracle dba 8715254 Aug  7 16:36 arch.log1_253736.dbf.bz2
-rw-rw---- 1 oracle dba 9187761 Aug  7 18:01 arch.log1_253737.dbf.bz2
-rw-rw---- 1 oracle dba 8758192 Aug  7 18:15 arch.log1_253738.dbf.bz2
-rw-rw---- 1 oracle dba 8809969 Aug  7 20:01 arch.log1_253739.dbf.bz2

Here is one way to do it:

$ x=253737; while [ -f arch.log1_$x.dbf.bz2 ]; do bzip2 -dkv arch.log1_$x.dbf.bz2; ((x+=1)); done
  arch.log1_253737.dbf.bz2: done
  arch.log1_253738.dbf.bz2: ...

The above method is probably best if you are using the 1988 version of the Korn shell (the standard shell on most commercial UNIX, and also describing the free pdksh). If you are unlucky enough to be using an actual Bourne shell or an Almquist shell derivative, you might replace ((x+=1)) with x=`expr $x + 1` (and think about getting a new shell).

However, if you use either the GNU BASH shell, or the updated Korn shell from 1993, new features where introduced that make this somewhat more succinct (assuming that you are willing to enter the concluding sequence number):

$ /usr/dt/bin/dtksh
$ for ((x=253737; x<=253785; x++)); do bzip2 -dkv arch.log1_$x.dbf.bz2; done
  arch.log1_253737.dbf.bz2: done
  arch.log1_253738.dbf.bz2: ...

Specifically, a numeric "for" and also the ++ increment operator will not work in ksh88 - they are new features. Note that double parenthesis in both examples triggers numeric evaluation.

Unfortunately, BASH also lacks a few standard features of ksh88 (primarily the "print" statement), complicating the question of portable scripting considerably, and necessitating multiple shells on Linux.

If you are on a system with the complete GNU COREUTILS package (typically Linux), there is also a program called "seq" that can be useful. Here are a few examples of seq:

-bash-3.00$ seq 5
1
2
3
4
5
-bash-3.00$ seq 6 10
6
7
8
9
10
-bash-3.00$ seq 0 2 10
0
2
4
6
8
10

seq's output can also be tailored with text:

-bash-3.00$ seq -f arch.log1_%g.dbf 735187 735189
arch.log1_735187.dbf
arch.log1_735188.dbf
arch.log1_735189.dbf

Using program substitution, I can unpack only a specific range of files from a 7-ZIP archive containing a much larger set:

-bash-3.00$ 7za x arch1.7z `seq -f arch.log1_%g.dbf 735187 735189`

7-Zip (A) 4.42  Copyright (c) 1999-2006 Igor Pavlov  2006-05-14
p7zip Version 4.42 (locale=en_US.UTF-8,Utf16=on,HugeFiles=on,2 CPUs)

Processing archive: arch1.7z

Extracting  arch.log1_735187.dbf
Extracting  arch.log1_735188.dbf
Extracting  arch.log1_735189.dbf

Everything is Ok

Note my use of `program...` above - be aware that this is old, Bourne shell syntax. The newer nomenclature of $(program...) is advised because you can nest several levels of program substitution. seq is also useful for turning the standard list-iterative "for" of the Bourne shell into an even more powerful numeric "for" than is in ksh93/BASH.

Of course, using the old syntax within command substitution is perfectly acceptable:

-bash-3.00$ 7za x arch1.7z $(x=735187; while [ $x -le 735189 ]; do echo arch.log1_$x.dbf; ((x+=1)); done)

7-Zip (A) 4.42  Copyright (c) 1999-2006 Igor Pavlov  2006-05-14
p7zip Version 4.42 (locale=en_US.UTF-8,Utf16=on,HugeFiles=on,2 CPUs)

Processing archive: arch1.7z

Extracting  arch.log1_735187.dbf
Extracting  arch.log1_735188.dbf
Extracting  arch.log1_735189.dbf

Everything is Ok
Did you find this article useful? Send an email to chas@syro.org.