Skip to content

Instantly share code, notes, and snippets.

@akatrevorjay
Last active May 7, 2023 14:52
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save akatrevorjay/9f6d1c83107fcdf4fed28d298769cfe0 to your computer and use it in GitHub Desktop.
Save akatrevorjay/9f6d1c83107fcdf4fed28d298769cfe0 to your computer and use it in GitHub Desktop.
Resume partial dd transfer
#!/bin/bash -e
# Blocksize to truncate to and buffer by
BS=${BS:-4096}
SELF="`basename $0`"
death() { echo "$SELF:" "$@" >&2; exit 1; }
[ $# -eq 2 ] || death "Usage: $SELF original copy"
SRC="$1"; DST="$2"
# Got SRC?
[ -f "$SRC" ] || death "$SRC: No such file"
# Calculate the number of $BS to skip before we start copying. Default to zero.
SKIP=0; [ ! -f "$DST" ] || SKIP=$(( $(wc --bytes "$DST" | awk '{print $1}' ) / $BS ))
# Do the actual copying.
dd if="$SRC" of="$DST" conv=notrunc bs=$BS skip=$SKIP seek=$SKIP
@Cqoicebordel
Copy link

Cqoicebordel commented May 3, 2023

FYI, there is an issue, as dd is always copying the last (partial) block of the file, because of rounding.
I'm looping over a big list of big files, and have to resume a lot, and that "bug" is not ideal.
Here's how I corrected it :

#!/bin/bash -e

# Blocksize to truncate to and buffer by
BS=${BS:-4096}

SELF="`basename $0`"
death() { echo "$SELF:" "$@" >&2; exit 1; }

[ $# -eq 2 ] || death "Usage: $SELF original copy"
SRC="$1"; DST="$2"

# Got SRC?
[ -f "$SRC" ] || death "$SRC: No such file"

# Compare size of both files
SRCSIZE=$(wc --bytes "$SRC" | awk '{print $1}' )
DSTSIZE=0; [ ! -f "$DST" ] || DSTSIZE=$(wc --bytes "$DST" | awk '{print $1}' )

if [ $SRCSIZE -ne $DSTSIZE ]; then
	# Calculate the number of $BS to skip before we start copying. Default to zero.
	SKIP=0; [ ! -f "$DST" ] || SKIP=$(( $(wc --bytes "$DST" | awk '{print $1}' ) / $BS ))

	[ $SKIP -eq 0 ] || echo "Continuing from $SKIP"

	# Do the actual copying.
	dd if="$SRC" of="$DST" conv=notrunc bs=$BS skip=$SKIP seek=$SKIP status=progress
else
	echo "Files have the same sizes"
fi

Granted I could have reused DSTSIZE in the SKIP calculation, but got lazy.
Note also I added the status=progress to dd to fit my personal preferences.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment