Last active
September 1, 2023 22:47
-
-
Save ernstki/b6e66e2f4163f583387f8656dde0640a to your computer and use it in GitHub Desktop.
[WIP] The standard 'md5sum' implemented as a Bash function for (older?) macOS
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env bash | |
# h/t: https://stackoverflow.com/a/28776166 | |
if ( return 0 2>/dev/null ); then sourced=1; else sourced=0; fi | |
# fail on unset variables unless sourced from another script | |
if (( !sourced )); then set -u; fi | |
# set TRACE=1 in the environment to enable execution tracing | |
if (( ${TRACE:-} )); then set -x; fi | |
_md5sum() { | |
if [[ $(uname -s) == Darwin ]]; then | |
# && ! command -v md5sum &>/dev/null | |
if [[ ${1:-} == '-c' ]]; then | |
# and when 'md5sum' fails it looks like this, so emulate that | |
# $ md5sum /etc/passwd | tr 1-4 6-9 | md5sum -c - | |
# /etc/passwd: FAILED | |
# md5sum: WARNING: 1 of 1 computed checksums did NOT match | |
# otherwise | |
# $ md5sum /etc/passwd | md5sum -c - | |
# /etc/passwd: OK | |
shift | |
local failed=0 total=0 | |
while read sum filename; do | |
if [[ $($FUNCNAME $filename) == $sum ]]; then | |
echo "$filename: OK" | |
else | |
echo "$filename: FAILED" | |
failed=$(( failed + 1 )) | |
fi | |
total=$(( total + 1 )) | |
done < <( cat ${@:+"$@"} ) | |
# useless use of cat for compatibility with the real 'md5sum', | |
# which already knows how to read from stdin if any argument is '-' | |
if (( failed )); then | |
echo "md5sum: WARNING: $(( failed )) of $(( total )) checksums did NOT match" | |
return 1 | |
fi | |
else | |
# recent *BSD have a '-n' which puts the output in "normal" form; | |
# (older?) macOS doesn't have this flag | |
# | |
# so tranform from md5's format, which is: | |
# $ md5 /etc/passwd | |
# MD5 (/etc/passwd) = 578778de897a870096cd897e6f967b5d | |
# $ echo HI | md5 | |
# 39d2b1ae41c609d04d9bbcde036940d8 | |
# | |
# if no filenames args are passed, 'md5sum's behavior is to just | |
# sit there and wait for stdin | |
if [[ $# -gt 0 ]]; then | |
for file in "$@"; do | |
md5 "$file" | sed -E 's/.*\((.+)\) = ([[:xdigit:]]+)/\2 \1/' | |
done | |
else | |
# reading from stdin | |
echo "$(md5) -" | |
fi | |
fi | |
else | |
md5sum ${@:+"$@"} | |
fi | |
} # _md5sum | |
# if we were sourced, do nothing; otherwise run with arguments | |
if (( !sourced )); then | |
_md5sum ${@:+"$@"} | |
fi |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
SHELL = bash | |
DIM := $(shell tput dim) | |
RESET := $(shell tput sgr0) | |
## tell 'md5sum' that it's under test | |
#TESTING = 1 | |
#export TESTING | |
check: test | |
test: have-md5-in-path have-md5sum-in-path md5sum \ | |
read-from-stdin read-filename read-multiple-filenames \ | |
check-from-stdin check-from-filename check-from-multiple-filenames | |
read-from-stdin: | |
@echo -e "\n$(DIM)## $@$(RESET)" >&2 | |
diff -u <(echo HI | command md5sum) <(echo HI | ./md5sum) | |
read-filename: /etc/passwd | |
@echo -e "\n$(DIM)## $@$(RESET)" >&2 | |
diff -u <(command md5sum $<) <(./md5sum $<) | |
read-multiple-filenames: /etc/passwd /etc/group /etc/hosts /etc/aliases | |
@echo -e "\n$(DIM)## $@$(RESET)" >&2 | |
diff -u <(command md5sum $^) <(./md5sum $^) | |
check-from-stdin: | |
@echo -e "\n$(DIM)## $@$(RESET)" >&2 | |
diff -u <(echo HI | command md5sum | command md5sum -c) <(echo HI | command md5sum | ./md5sum -c) | |
check-from-filename: MD5SUMS | |
@echo -e "\n$(DIM)## $@$(RESET)" >&2 | |
diff -u <(command md5sum -c $<) <(./md5sum -c $<) | |
check-from-multiple-filenames: MD5SUMS MD5SUMS2 | |
@echo -e "\n$(DIM)## $@$(RESET)" >&2 | |
diff -u <(command md5sum -c $^) <(./md5sum -c $^) | |
MD5SUMS: | |
md5sum * > $@ | |
MD5SUMS2: MD5SUMS | |
# `tail -r` is macOS/BSD thing; otherwise use `tac` | |
if [[ $$(uname -s) == Darwin ]]; then \ | |
tail -r $< > $@; \ | |
else \ | |
tac $< > $@; \ | |
fi | |
clean: | |
-rm MD5SUMS* | |
have-md5-in-path: | |
ifeq ($(shell command -v md5),) | |
$(error Need 'md5' in the search path to run tests) | |
endif | |
have-md5sum-in-path: | |
ifeq ($(shell command -v md5sum),) | |
$(error Need 'md5sum' in the search path to run tests) | |
endif |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
This is a work-in-progress.
macOS doesn't have the standard
md5sum
utility, except if you install it from Homebrew or MacPorts (package:md5sha1sum
).This bit of shell script implements the standard behavior of
md5sum
, including reading and writing from a pipe, in Bash script, wrapped around the *BSDmd5
utility, which macOS does have.Testing
It works for some of the common use cases, but others not. Running
make -f •Makefile
after cloning the gist as a Git repo locally will run the tests.