plumb: plan9 plumber-like script - scripts - various script and utils
HTML git clone git://z3bra.org/scripts
DIR Log
DIR Files
DIR Refs
---
DIR commit 6ca2b5c87e6b9b8603995b3db4968f6e67f3b2f0
DIR parent 25f6018d03344905687619e01ec5091dd949d83c
HTML Author: Willy Goiffon <dev@z3bra.org>
Date: Thu, 20 Aug 2026 23:06:10 +0000
plumb: plan9 plumber-like script
Diffstat:
A plumb | 128 +++++++++++++++++++++++++++++++
1 file changed, 128 insertions(+), 0 deletions(-)
---
DIR diff --git a/plumb b/plumb
@@ -0,0 +1,128 @@
+#!/bin/sh
+
+# all these have the same result:
+#
+# plumb -u https://z3bra.org/z3bra.png
+# echo https://z3bra.org/z3bra.png | wl-copy; plumb
+# echo https://z3bra.org/z3bra.png | plumb -s
+# curl -s https://z3bra.org/z3bra.png | plumb -
+
+usage() {
+ echo "usage: $(basename $0) [-hs] [-u uri]" >&2
+}
+
+justtype() {
+ dos2unix -q | tr -d ' ' |cut -d: -f2 | cut -d\; -f1
+}
+
+gophertype() {
+ file=$(basename "$1")
+ type=$(echo "$1" | cut -d/ -f4)
+ case $type in
+ 9) printf 'application/octet-stream\n' ;;
+ I) printf 'image/%s\n' "${file##*.}" ;;
+ g) printf 'image/gif\n' ;;
+ *) printf 'text/plain\n' ;;
+ esac
+}
+
+pipe() {
+ [ -n "$proto" ] && curl -sSkL "$1" -o -
+ [ -z "$proto" ] && cat "$1"
+}
+
+getclip() {
+ wl-paste -p 2>/dev/null
+}
+
+# default mimetype
+mime=''
+clip="$(getclip)" # get uri from clipboard by default
+
+while getopts "hsu:v-" OPT; do
+ case $OPT in
+ s) input="$(cat)" ;; # read uri from stdin
+ u) input="$OPTARG" ;; # pass uri as argument
+ v) verbose=1 ;;
+ h) usage; exit 0 ;;
+ *) usage; exit 1 ;;
+ esac
+done
+
+shift $((OPTIND-1))
+
+[ $# -gt 0 ] && input="$1"
+
+# read file *content* to stdin when uri is -
+[ "$1" = "-" ] && {
+ input=$(mktemp -p /tmp plumb.XXXXXXXX)
+ cat > $input
+}
+
+uri="${input:-$clip}"
+
+[ -z "$uri" ] && exit 1
+
+proto="$(echo "$uri" | sed -n 's,^\([^:]*\)://.*,\1,p')"
+
+if [ -z "$proto" ]; then
+ if [ -e "$uri" ]; then
+ mime=$(file -i "$uri" | justtype)
+ elif getent hosts "$uri" >/dev/null; then
+ # assume website if name is resolvable
+ mime="text/html"
+ else
+ uri="https://duckduckgo.com/?q=$uri"
+ fi
+else
+ case $proto in
+ vmrc) mime=application/x-vmrc ;;
+ https|http) mime=$(curl -skI "$uri" | grep -ioE 'content-type:[^;]*' | justtype) ;;
+ gopher)
+ mime=$(gophertype "$uri")
+ uri=$(echo $uri | sed 's,gopher://,http://phroxy.z3bra.org/,')
+ ;;
+ telnet|ssh)
+ mime="$proto"
+ uri="${uri#${proto}://}"
+ host="${uri%%:*}"
+ port="${uri##*:}"
+ ;;
+ esac
+
+ [ -z "$mime" ] && mime=$(curl -sk "$uri" | cut -b 1-100 | file -i - | justtype)
+fi
+
+# verbose mode
+[ -n "$verbose" ] && printf 'uri: %s\nproto: %s\nmime: "%s"\n' "$uri" "$proto" "$mime"
+
+case "$mime" in
+ text/html) exec ${BROWSER:-firefox-nightly} "$uri" ;;
+ text/xml) exec ${BROWSER:-firefox-nightly} "$uri" ;;
+ image/gif) exec mplayer -loop 0 "$uri" ;;
+ audio/*) exec mpv -cache 512 "$uri" ;;
+ video/*) exec mpv -cache 512 "$uri" ;;
+ image/*)
+ if [ -n "$proto" ]; then
+ tmp=$(mktemp -p /tmp plumb.XXXXXXXX)
+ pipe "$uri" > $tmp
+ uri=$tmp
+ fi
+ imv-wayland "$uri"
+ ;;
+ text/*)
+ if [ -n "$proto" ]; then
+ tmp=$(mktemp -p /tmp plumb.XXXXXXXX)
+ pipe "$uri" > $tmp
+ uri=$tmp
+ fi
+ tty -s && exec less "$uri" || exec st -e less "$uri"
+ ;;
+ application/octet-stream) exec $(tofi-run) "$uri" ;;
+ application/x-vmrc) exec vmrc "$uri" ;;
+ application/x-java-jnlp-file) exec javaws "$uri" ;;
+ application/vnd.openxmlformats-*) libreoffice "$uri" ;;
+ telnet) exec st -e telnet "$host" "${port:-proto}" ;;
+ ssh) exec st -e ssh -P "${port:-$proto}" "$host" ;;
+ *) exec ${BROWSER:-surf} "$uri" ;;
+esac