How to determine eod

1.6k Views Asked by At

I would like to read various partitions from a DDS tape using a script
At the moment I am using the following script

TAPE=/dev/nst0         
BLOCK_SIZE=32768        
COUNTER=1
END_OF_DATA=120

while [  $COUNTER -lt $END_OF_DATA ] 
do      
       dd if=$TAPE bs=$BLOCK_SIZE of=file_$COUNTER  
       let COUNTER+=1 
done

However, as you can see my script can read at maximum 120 partitions.

How can I modify this code to enable the script to recognise the end of data of the tape automatically

Thanks

2

There are 2 best solutions below

3
On BEST ANSWER

You can keep comparing the report with block size. And yes you have to open the device only once and keep reading from it.

TAPE=/dev/nst0 
BLOCK_SIZE=32768
COUNTER=1

while [ "$(dd bs="$BLOCK_SIZE" of="file_$COUNTER" 2>&1 count=1 | awk '/bytes/ { print $1 }')" -eq "$BLOCK_SIZE" ]; do
    let ++COUNTER
done < "$TAPE"

Script is tested with a file.

You can also remove the last file if last number of bytes read was just 0:

while
    BYTES_READ=$(dd bs="$BLOCK_SIZE" of="file_$COUNTER" 2>&1 count=1 | awk '/bytes/ { print $1 }')
    [ "$BYTES_READ" -eq "$BLOCK_SIZE" ]
do
    let ++COUNTER
done < "$TAPE"

[ "$BYTES_READ" -eq 0 ] && rm -f "file_$COUNTER"

If you want to send a message while you process the tape, you can use redirections and use another file descriptor for it:

TAPE=temp
BLOCK_SIZE=32768
COUNTER=1

while
    FILE="file_$COUNTER"
    echo "Reading $BLOCK_SIZE from $TAPE and writing it to file $FILE."
    BYTES_READ=$(dd bs="$BLOCK_SIZE" of="$FILE" count=1 2>&1 <&4 | awk '/bytes/ { print $1 }')
    echo "$BYTES_READ bytes read."
    [ "$BYTES_READ" -eq "$BLOCK_SIZE" ]
do
    let ++COUNTER
done 4< "$TAPE"

[ "$BYTES_READ" -eq 0 ] && rm -f "$FILE"

Example output:

Reading 32768 from temp and writing it to file file_1.
32768 bytes read.
Reading 32768 from temp and writing it to file file_2.
32768 bytes read.
Reading 32768 from temp and writing it to file file_3.
32768 bytes read.
Reading 32768 from temp and writing it to file file_4.
32768 bytes read.
Reading 32768 from temp and writing it to file file_5.
32268 bytes read.

Another option is to just send your echos to /dev/stderr.

echo "Reading $BLOCK_SIZE from $TAPE and writing it to file $FILE." >&2

To make it a little faster also, use exec inside the subshell to prevent extra fork:

BYTES_READ=$(exec dd ...)
1
On

As I said in a comment, I'm not very proficient with this issue, but as "dd stops at the end of each partition", why don't you simply read until there is nothing more to read?

TAPE=/dev/nst0         
BLOCK_SIZE=32768        
COUNTER=1

while true 
do      
       dd if=$TAPE bs=$BLOCK_SIZE of=file_$COUNTER

       if [ \! -s file_$COUNTER ]
       then
               # clean-up empty file and exit the loop
               rm file_$COUNTER
               break
       fi
       let COUNTER+=1 
done

(untested)