Search code examples
bashshellddmt

How to determine eod


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


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