I would like to share another wrapper based on the pv command ( because we love progress bars!! ).

As part of my work in NextCloudPi, I am constantly copying images to an SD card to test the latest build. The classic Linux way of doing this is by using the dd command

# dd bs=4M if=NextCloudPi_02-06-18.img of=/dev/sdd && sync

We all know the caveats of using this command, namely

The syntax is ugly

Better not forget that last sync call

There is no safety check to prevent you to mistakenly overwriting your root partition

If the SD card showed up in a different place, let’s say /dev/sde, you end up with a new 4GB file in /dev/sdd, and still you think that the copy went well.

Even though we now have status=progress for dd, I still like the progress bar better.

Usage

The usage is simple

$ ddsd --help Usage: ddsd (-b/--block-size <block size>) <img_file> <block_device>

The only optional argument is the block size. For instance

# ddsd -b4M NextCloudPi_02-06-18.img /dev/sdc

As in the dd command, the optimum value for this parameter depends on the specifics of the operating system, buffers and hardware. If not specified, the following rule will be used ( from man pv )

The default buffer size is the block size of the input file’s filesystem multiplied by 32 (512KiB max), or 400KiB if the block size cannot be determined.

Installation

Get the script and make it executable. You can do this in two lines, but better inspect it first. Don’t trust anyone blindly.

sudo wget https://raw.githubusercontent.com/nachoparker/ddsd/master/ddsd -O /usr/local/bin/ddsd sudo chmod +x /usr/local/bin/ddsd

Code

#!/bin/bash # pv wrapper to safely flash images to an SD card # # Copyleft 2017 by Ignacio Nunez Hernanz <nacho _a_t_ ownyourbits _d_o_t_ com> # GPL licensed (see end of file) * Use at your own risk! # # Usage: # ddsd (-b <block size>) <img_file> <block_device> # # More details at ownyourbits.com print_usage() { echo "Usage: $0 (-b/--block-size <block size>) <img_file> <block_device>"; } ddsd() { # parse arguments local OPTS OPTS=$( getopt -o hb: -l block-size: -l help -- "$@" 2>/dev/null ) [[ $? -ne 0 ]] && { echo "error parsing arguments"; return 1; } eval set -- "$OPTS" while true; do case "$1" in -h|--help ) print_usage; return 0 ;; -b|--block-size) local BS=$2; shift 2 ;; --) shift; break ;; esac done # block size argument [[ "$BS" != "" ]] && local ARG="-B $BS" local IF="$1" local OF="$2" # checks type pv &>/dev/null || { echo "install pv first" ; return 1; } [[ $# -ne 2 ]] && { print_usage ; return 1; } [[ -f "$IF" ]] || { echo "$IF does not exist" ; return 1; } [[ -e "$OF" ]] || { echo "$OF does not exist" ; return 1; } [[ -b "$OF" ]] || { echo "$OF is not a block device"; return 1; } awk '{ print $1 }' /proc/mounts | grep -q "$OF" && { echo "$OF is currently mounted"; return 1; } # CTRL-C trap cancel() { echo "cancelling..."; kill $PID; wait $PID; exit 1; } trap cancel SIGINT # flashing echo "flashing..." pv $ARG "$IF" > "$OF" & PID=$! wait $PID || return 1 # syncing echo -n "syncing... " && sync && echo "done" } ddsd $@ # License # # This script is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This script is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this script; if not, write to the # Free Software Foundation, Inc., 59 Temple Place, Suite 330, # Boston, MA 02111-1307 USA