#!/usr/bin/env bash # # base16 # # Base16 encode/decode data. # # Author: Emanuel Duss # set -o errexit set -o nounset set -o pipefail print_usage(){ cat << EOI Usage: base16 [OPTION]... [FILE] Base16 (Hex) encode or decode FILE, or standard input, to standard output. With no FILE, or when FILE is -, read standard input. Options: -d decode data -i when decoding, ignore non-alphabet characters -w COLS wrap encoded lines after COLS character (default 76). Use 0 to disable line wrapping -h display this help and exit The data are encoded as described for the base16 alphabet in RFC 4648. When decoding, the input may contain newlines in addition to the bytes of the formal base64 alphabet. Use -i to attempt to recover from any other non-alphabet bytes in the encoded stream. EOI } check_dependencies(){ local FAIL=0 local MISSING="" for tool in $@ do if ! hash "$tool" &> /dev/null then MISSING="$MISSING, $tool" FAIL=1 fi done if [[ "$FAIL" == 1 ]] then echo "Missing dependency: ${MISSING/, }." exit 1 fi } parse_arguments(){ WRAP_COLS="76" while getopts diw:h name do case $name in d) DECODE="1" ;; i) IGNORE_GARBAGE="1" ;; w) WRAP="1" WRAP_COLS="$OPTARG" ;; h) print_usage exit ;; ?) print_usage >&2 exit 1 ;; esac done } hex_to_binary(){ perl -e ' local $/; $i = <>; $i =~ s/[\r\n]//g; if ($i =~ /[^0-9a-fA-F]/){ print STDERR "base16: invalid input\n"; exit 1; } print pack "H*", $i;' } hex_to_binary_ignore_garbage(){ perl -e ' local $/; $i = <>; $i =~ s/[^0-9a-fA-F\n\r]//g; print pack "H*", $i' } binary_to_hex(){ # hexdump -ve '1/1 "%.2x"' perl -e ' local $/; print unpack "H*", <>' } main(){ check_dependencies perl parse_arguments "$@" shift $(($OPTIND - 1)) # Only one file is allowed if [[ "$#" > 1 ]] then echo -e "base16: extra operand '$1'" echo "Try 'base16 -h for more information." exit 1 fi # Use STDIN (-) if $1 is not set FILE="${1:--}" # Decode if [[ -n "${DECODE:-}" ]] then if [[ -n "${IGNORE_GARBAGE:-}" ]] then cat "$FILE" | hex_to_binary_ignore_garbage else cat "$FILE" | hex_to_binary fi # Encode else if [[ "$WRAP_COLS" == "0" ]] then cat "$FILE" | binary_to_hex | tr -d '\n' else cat "$FILE" | binary_to_hex | fold -w "$WRAP_COLS" echo # Print newline at the end fi fi } main "$@"