Question

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

Was it helpful?

Solution

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

OTHER TIPS

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)

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top