diff --git a/README.md b/README.md index 96d129d..01d1e9d 100644 --- a/README.md +++ b/README.md @@ -11,3 +11,4 @@ * [GHMD](./ghmd.sh): a command suite to set up your own self-hosted Git repositories * [Multicities](./cities.sh): Neocities static site manager with multiple account support * [Rusty Checker](./rusty-checker.sh): quickly check if a public FOSS project is written in Rust (or another language that you pass to the script) +* [Image Transfer](./it.sh): a more convenient wrapper around dd for writing and reading removable media images diff --git a/it.sh b/it.sh new file mode 100755 index 0000000..950c3bd --- /dev/null +++ b/it.sh @@ -0,0 +1,49 @@ +#!/bin/sh +# Image Transfer: a simple script to transfer raw images to/from removable media +# in a safer manner +# Depends on basename, dd, fzf +# Usage: it.sh w|r image-file +# Created by Luxferre in 2026, released into public domain + +get-removables() { + for ddir in /sys/block/*; do + if grep -q 1 ${ddir}/removable; then + dbase="$(basename $ddir)" + dvendor="$(cat ${ddir}/device/vendor)" + dmodel="$(cat ${ddir}/device/model)" + printf "%s\t%s %s" "$dbase" "$dvendor" "$dmodel" + fi + done +} + +DEF_DD_OPTS="status=progress" +[ -z "$DD_OPTS" ] && DD_OPTS="bs=2M" +[ -z "$SUDO" ] && SUDO="sudo" +if [ -z "$1" ]; then + echo "No operation! Select w or r" + exit 1 +fi +if [ -z "$2" ]; then + echo "No target file specified!" + exit 1 +fi +TARGET_DRIVE="/dev/$(get-removables | fzf --prompt "Select the drive: " | cut -f 1)" + +RUN_COMMAND="" +if [ "$1" = "w" ]; then + RUN_COMMAND="dd if=$2 of=$TARGET_DRIVE $DEF_DD_OPTS $DD_OPTS" + if [ ! -w $TARGET_DRIVE ]; then + RUN_COMMAND="$SUDO $RUN_COMMAND" + fi +elif [ "$1" = "r" ]; then + RUN_COMMAND="dd of=$2 if=$TARGET_DRIVE $DEF_DD_OPTS $DD_OPTS" + if [ ! -r $TARGET_DRIVE ]; then + RUN_COMMAND="$SUDO $RUN_COMMAND" + fi +else + echo "Invalid operation! Select w or r" + exit 1 +fi +echo "Starting the operation..." +$RUN_COMMAND && echo "Operation successful!" || echo "Operation completed with errors!" +