Siempre me encuentro googleando a ver cómo se hacía esto... como ya estoy cansado, lo anoto acá.
El comando dd no es muy comunicativo. Simplemente da un informe cuando termina. Como a veces lo usamos para copiar cosas muy largas, está bueno poder monitorear lo que hace.
Sin embargo, si le mandamos una señal USR1, imprime el status actual por stdout.
La solución que a mí más me gusta es mandar el dd a background y mandarle la señal periódicamente para que muestre el estado cada, por ejemplo, 10 segundos. Cuando termina va a dar el estado final y va a fallar el último kill (lo que uso como condición para salir del loop).
Las variables al principio son para poder configurarlo fácilmente
INFILE=input.bin
OUTFILE=output.bin
OPTIONS="bs=512 count=10"
# el tiempo entre un monitoreo y otro (en segundos)
SLEEPTIME=10
dd if=${INFILE} of=${OUTFILE} ${OPTIONS} &
# monitorear el avance del 'dd' que está en background (kill -SIGUSR1 fuerza a que el dd muestre su status actual)
while kill -n SIGUSR1 $! ; do
sleep ${SLEEPTIME}
done