├── .travis.yml ├── Makefile ├── README.md ├── bin ├── background ├── base ├── color ├── crypt ├── cx ├── d ├── dedit ├── dimensions ├── f ├── fch ├── ffmpeg-concat ├── fg ├── fullpath ├── getparent ├── getppid ├── gifify ├── gud ├── human ├── isempty ├── isnum ├── last ├── lorem ├── mpvimg ├── nuke-iptables ├── opn ├── pack ├── pad ├── pid2name ├── png2jpg ├── proxmox-ram-provisioned ├── rgen ├── rot13 ├── sloc ├── steam_renice_daemon.sh ├── tlog ├── tmpsh ├── trash ├── unpack ├── upl ├── wayland_or_x11 ├── webmify └── zfs-nuke-snapshots ├── check ├── check.sh ├── etc └── init.d │ └── steam_renice_daemon ├── legacy ├── LICENSE ├── README.md ├── asahi │ ├── README.md │ ├── asahi-brightnessctl │ ├── asahi-hyprland │ ├── asahi-keysctl │ └── asahi-kitty ├── dict ├── dl ├── dmoji ├── ghmd2html ├── keys ├── linux │ ├── README.md │ ├── backup-gnome.sh │ ├── battery │ ├── bright │ ├── maild │ ├── menu │ ├── rbag │ ├── temp │ └── x9term ├── lock ├── mag ├── md2html ├── mmt ├── note ├── openbsd │ ├── README.md │ ├── allowrecord │ ├── grab_ports.sh │ ├── interface │ ├── pledgetrace │ ├── seq │ └── watch ├── pape ├── paped ├── pdf2txt ├── quote ├── record ├── rice ├── rotate ├── scrap ├── square ├── vol ├── wallgen ├── yt ├── ytdlq └── ytknife └── non-shell ├── README.md ├── lower ├── randmac ├── squeeze ├── trim ├── upper └── urls /.travis.yml: -------------------------------------------------------------------------------- 1 | script: 2 | - shellcheck -s sh bin/* 3 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | all: install 2 | 3 | install: 4 | mkdir -p ${HOME}/.local/bin 5 | install -m 0755 bin/* ${HOME}/.local/bin/ 6 | install -m 0755 non-shell/* ${HOME}/.local/bin/ 7 | 8 | test: 9 | sh check.sh 10 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # bin 2 | 3 | Helpful things I use on a daily basis. 4 | 5 | Do more with less. I only use POSIX sh. 6 | 7 | -------- 8 | 9 | Feel free to steal whatever you like. 10 | 11 | Leaving the comment heading would be nice. ❤ 12 | 13 | -------- 14 | 15 | GitHub issues and pull requests are welcome. 16 | 17 | If you appreciate my work, a star is a nice gesture. 🌟 18 | 19 | ### See also: 20 | 21 | [dots](http://github.com/mitchweaver/dots) - dotfiles 22 | -------------------------------------------------------------------------------- /bin/background: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # http://github.com/mitchweaver/bin 4 | # 5 | # extremely messy wallpaper setter 6 | # 7 | 8 | save_location=${HOME}/.local/wallpaper 9 | 10 | die() { 11 | >&2 printf '%s\n' "$*" 12 | exit 1 13 | } 14 | 15 | usage() { 16 | >&2 cat </dev/null || die 'install swaybg dummy' 34 | ;; 35 | *) 36 | command -v xwallpaper >/dev/null || die 'install xwallpaper dummy' 37 | esac 38 | [ -f "$save_location" ] || die "$save_location not found" 39 | } 40 | 41 | # reads size of the image, if smaller than 24 it should be tiled 42 | should_tile() { 43 | read -r size _ << EOF 44 | $(du -k "$1") 45 | EOF 46 | 47 | echo "Size: $size" 48 | # tile image if its smaller than 24kb 49 | if [ "$size" -lt 24 ] ; then 50 | echo "Setting mode to --tile" 51 | MODE=tile 52 | fi 53 | } 54 | 55 | do_copy() { 56 | if [ -f "$1" ] ; then 57 | cp -f "$1" "$save_location" 58 | else 59 | die "$1 not found" 60 | fi 61 | } 62 | 63 | set_pape() { 64 | case $(wayland_or_x11) in 65 | *wayland*) 66 | if pgrep -f Hyprland >/dev/null || pgrep -f sway >/dev/null ; then 67 | pkill swaybg 68 | nohup swaybg -m "${MODE:-fill}" -i "$1" >/dev/null 2>&1 & 69 | elif pgrep -f kwin_wayland >/dev/null ; then 70 | 71 | # ------------------------------------------------------------------------ 72 | # KDE wont actually do the change if the old path is the same as the new path 73 | # since this script is meant to be run on login to change the wallpaper 74 | # to whatever is ~/.local/wallpaper by default, we need to trick KDE 75 | # into thinking its a new path everytime... 76 | cp "$1" /tmp/a 77 | plasma-apply-wallpaperimage /tmp/a >/dev/null 2>&1 78 | /bin/rm /tmp/a 79 | # ------------------------------------------------------------------------ 80 | 81 | dbus-send \ 82 | --session \ 83 | --dest=org.kde.plasmashell \ 84 | --type=method_call \ 85 | /PlasmaShell \ 86 | org.kde.PlasmaShell.evaluateScript \ 87 | "string: var Desktops = desktops(); 88 | for (i=0;i&2 cat </dev/null ; then 10 | exit 1 11 | fi 12 | 13 | pixel="$(slurp -p)" 14 | 15 | # error out if user exited slurp without clicking 16 | [ "$pixel" ] || exit 1 17 | 18 | read -r _ _ hex _ <&2 printf '%s\n' "$*" 12 | exit 1 13 | } 14 | 15 | usage() { 16 | >&2 cat </dev/null | \ 35 | dd ibs=1 obs=1 count=8 2>/dev/null | \ 36 | sed 's/\-//g' 2>/dev/null || printf '%s\n' $$ 37 | } 38 | 39 | encrypt() { 40 | openssl \ 41 | enc \ 42 | -aes-256-cbc \ 43 | -a \ 44 | -salt \ 45 | -pbkdf2 \ 46 | -in "$1" 47 | } 48 | 49 | decrypt() { 50 | openssl \ 51 | enc \ 52 | -aes-256-cbc \ 53 | -d \ 54 | -a \ 55 | -salt \ 56 | -pbkdf2 \ 57 | -in "$1" 58 | } 59 | 60 | main() { 61 | case ${1#-} in 62 | h|-help) 63 | usage 64 | ;; 65 | d) 66 | shift 67 | case ${1#-} in 68 | i) 69 | shift 70 | isfile "$1" || usage 71 | tmp=/tmp/$$-$(get_entropy).decrypt 72 | decrypt "$1" > "$tmp" || die "couldn't decrypt to '$tmp'" 73 | mv -f -- "$tmp" "${1%.crypt}" || die "couldn't name '$tmp' to '${1%.crypt}'" 74 | rm -f -- "$1" 75 | ;; 76 | *) 77 | isfile "$1" || usage 78 | decrypt "$1" 79 | esac 80 | ;; 81 | *) 82 | isfile "$1" || usage 83 | encrypt "$1" || die "Failed to encrypt '$1'" 84 | esac 85 | } 86 | 87 | main "$@" 88 | -------------------------------------------------------------------------------- /bin/cx: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # http://github.com/mitchweaver/bin 4 | # 5 | # cx - change executability 6 | # 7 | # toggle a file between executable / non-executable 8 | # 9 | 10 | for file ; do 11 | if [ -f "$file" ] ; then 12 | if [ -x "$file" ] ; then 13 | chmod -x "$file" 14 | else 15 | chmod +x "$file" 16 | fi 17 | else 18 | >&2 printf 'Error: %s does not exist.\n' "$file" 19 | fi 20 | done 21 | -------------------------------------------------------------------------------- /bin/d: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # http://github.com/mitchweaver 4 | # 5 | # "du for humans" 6 | # 7 | # note: optinally add -L to follow links 8 | # 9 | # -*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-* 10 | 11 | usage() { 12 | >&2 printf 'Usage: %s [-L links] \n' "${0##*/}" 13 | exit 1 14 | } 15 | 16 | case ${1#-} in 17 | h|-help) 18 | usage 19 | ;; 20 | l|L|-links) 21 | LINKS=L 22 | shift 23 | esac 24 | 25 | if [ -d "${1:-.}" ] ; then 26 | du -ahd$LINKS 1 "${1:-.}" 2>/dev/null | \ 27 | sort -rh | \ 28 | head -n 20 29 | elif [ -f "$1" ] ; then 30 | du -ah$LINKS "$1" 31 | fi 32 | -------------------------------------------------------------------------------- /bin/dedit: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # http://github.com/mitchweaver/bin 4 | # 5 | # open and edit a file from given locations with dmenu 6 | # 7 | # shellcheck disable=2086 8 | # 9 | 10 | # -*-*-*-*-*- settings -*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-* 11 | folders=\ 12 | """ 13 | ${HOME}/.local/dedit_bookmarks 14 | ${XDG_DOCUMENTS_DIR} 15 | ${XDG_DOCUMENTS_DIR}/notes 16 | ${HOME}/src/bin/bin 17 | ${HOME}/src/shit/bin 18 | ${HOME}/src/dots/Gentoo/notes/pkgs 19 | $(find ~/src/dots -maxdepth 2 -type d ! -path '*/.git*') 20 | """ 21 | #####$(printf '%s\n' ${HOME}/bin/*/) 22 | # -*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-* 23 | 24 | sel=\ 25 | $(\ 26 | for f in $folders ; do 27 | find -L "$f" \ 28 | -mindepth 1 \ 29 | -maxdepth 1 \ 30 | -type f \ 31 | ! -name "*/.git*" 2>/dev/null 32 | done | sed 's/.*\///g' | sort -u | menu --wide -p 'Edit:'\ 33 | ) 34 | 35 | [ "$sel" ] || exit 1 36 | 37 | for f in $folders ; do 38 | if [ -f "$f/$sel" ] ; then 39 | # printf 'opening: %s/%s' "$f" "$sel" 40 | if [ "$PLUMBER" ] ; then 41 | exec $PLUMBER -- "$f/$sel" 42 | else 43 | if uname -a | grep -i asahi >/dev/null ; then 44 | exec asahi-kitty --detach ${EDITOR:-vi} -- "$f/$sel" 45 | else 46 | exec kitty --detach ${EDITOR:-vi} -- "$f/$sel" 47 | fi 48 | # exec st -e ${EDITOR:-vi} -- "$f/$sel" 49 | fi 50 | fi 51 | done 52 | -------------------------------------------------------------------------------- /bin/dimensions: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # http://github.com/mitchweaver/bin 4 | # 5 | # get screen dimensions, ex: "1280 800" 6 | # 7 | # NOTE: This grabs the first result, the "primary" monitor. 8 | # I would love to get which monitor "has focus" (ie the pointer) instead. 9 | # If you find a way to do, please pull request. 10 | # 11 | # NOTE2: As xrandr is somewhat slow, I recommend exporting 12 | # this as a result in your ~/.xsession so it needn't 13 | # be calculated more than once. 14 | # 15 | 16 | xrandr --nograb --current --listactivemonitors | \ 17 | while read -r line ; do 18 | case $line in 19 | Monitors*) ;; 20 | *) 21 | w=${line%%/*} 22 | h=${line#*x} 23 | printf '%s %s\n' "${w##* }" "${h%%/*}" 24 | break 25 | esac 26 | done 27 | -------------------------------------------------------------------------------- /bin/f: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # http://github.com/mitchweaver/bin 4 | # 5 | # f - a tiny posix file searcher 6 | # 7 | # "find for normal humans" 8 | # 9 | # -*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-* 10 | 11 | usage() { 12 | >&2 cat <<"EOF" 13 | f - a tiny posix file searcher 14 | =============================================== 15 | Usage: f search terms 16 | 17 | [-f] search for a file 18 | [-d] search for a directory 19 | 20 | Examples: 21 | =============================================== 22 | 1. Search for a file named "foo.txt" in $PWD 23 | $ f foo.txt 24 | 25 | 2. Search for a directory named "bar.d" in /etc 26 | $ f -d /etc bar.d 27 | EOF 28 | exit 1 29 | } 30 | 31 | while [ "$1" ] ; do 32 | case ${1#-} in 33 | h) 34 | usage 35 | ;; 36 | f|d) 37 | case $1 in 38 | f|d) 39 | ;; 40 | *) 41 | usage 42 | esac 43 | t="-type $2" 44 | shift 1 45 | ;; 46 | *) 47 | case $# in 48 | 1) 49 | # if only given one term, it must be a search term 50 | # and the dir to search in is assumed to be $PWD 51 | p=. 52 | ;; 53 | 2) 54 | if [ -d "$1" ] ; then 55 | p=$1 56 | shift 57 | else 58 | usage 59 | fi 60 | ;; 61 | *) 62 | # we should never have zero or three arguments here 63 | usage 64 | esac 65 | break 66 | esac 67 | done 68 | 69 | # check if we still have arguments to search for 70 | [ "$1" ] || usage 71 | 72 | # shellcheck disable=2086 73 | exec find -L "$p" ! -path "$p" $t -iname "*${*}*" -maxdepth 10 2>/dev/null 74 | -------------------------------------------------------------------------------- /bin/fch: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # 3 | # http://github.com/mitchweaver/bin 4 | # 5 | # ████ ██ 6 | # ░██░ ░██ 7 | # ██████ █████ ░██ 8 | # ░░░██░ ██░░░██░██████ 9 | # ░██ ░██ ░░ ░██░░░██ 10 | # ░██ ░██ ██░██ ░██ 11 | # ░██ ░░█████ ░██ ░██ 12 | # ░░ ░░░░░ ░░ ░░ 13 | # 14 | # yet another fetch script 15 | # 16 | # Supports Linux and OpenBSD 17 | # 18 | # * Work in progress * 19 | # 20 | # --- Example output: ------ 21 | # 22 | # [tmp] $ ./fch 23 | # ┌─────────────────────────────────────┐ 24 | # │  mitch@dankpad.local.wvr.sh │ 25 | # ├─────────────────────────────────────┤ 26 | # │  ThinkPad X1 Carbon 7th │ 27 | # │  Gentoo 6.2.11-zen1-x86_64 │ 28 | # │  1034 │ 29 | # │  dwm │ 30 | # │  kitty │ 31 | # │  oksh │ 32 | # │  i5-8365U │ 33 | # │  3.7G/8.2G │ 34 | # │  52.0G/234G (22%) │ 35 | # │  0.79 0.68 0.32 │ 36 | # │  68.7°C │ 37 | # └─────────────────────────────────────┘ 38 | # 39 | # -*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-* 40 | 41 | # openbsd compat 42 | if ! command -v seq >/dev/null ; then 43 | seq() { 44 | jot "$@" 45 | } 46 | fi 47 | 48 | # shellcheck disable=2030,2034 49 | pr_space() { 50 | df -h 2>/dev/null | \ 51 | while read -r drive size used _ perc mountpoint _ ; do 52 | # only print line if drive is a physical device 53 | case ${drive##*/} in 54 | sd*|nvme*|rpool/*/root) 55 | case $mountpoint in 56 | */boot|*/efi) 57 | # ignore 58 | ;; 59 | *) 60 | printf "│  %s/%s " "$used" "$size" #"$perc" 61 | for i in $(seq $((length - ${#used} - ${#size} - 1)) ) ; do 62 | printf ' ' 63 | done 64 | printf ' │\n' 65 | esac 66 | esac 67 | done 68 | } 69 | 70 | # idea to get terminal font 71 | # get_font() { 72 | # font=$(strings <$(which st) | grep 'pixelsize=') 73 | # printf '%s\n' "${font%%:*}" 74 | # } 75 | 76 | mem() { 77 | case $(uname) in 78 | OpenBSD) 79 | # shellcheck disable=2034 80 | read -r _ _ real _ _ free _ cache _ swap </dev/null ; then 136 | temp 137 | else 138 | read -r tmp /dev/null ; then os=OpenBSD 166 | elif command -v pkgin >/dev/null ; then os=NetBSD 167 | elif command -v apk >/dev/null ; then os=Alpine 168 | elif command -v crux >/dev/null ; then os=CRUX 169 | elif command -v xbps-query >/dev/null ; then os=Void 170 | elif command -v ubuntu-bug >/dev/null ; then os=Ubuntu 171 | elif command -v apt-get >/dev/null ; then os=Debian 172 | elif command -v emerge >/dev/null ; then os=Gentoo 173 | elif command -v dnf >/dev/null ; then os=Fedora ; fi 174 | kern=$(uname -r | sed 's/-.*//') 175 | # kern=${kern%%-*} 176 | printf '%s %s\n' "$os" "$kern" 177 | } 178 | 179 | pr_line() { 180 | buf=$1 181 | # SC: "i is unused" 182 | # shellcheck disable=2034 183 | for i in r i c i n g $(seq "$3") ; do 184 | buf="$buf─" 185 | done 186 | printf '%s\n' "$buf$2" 187 | } 188 | 189 | pr_host() { 190 | h=$(hostname) 191 | host=$USER@$h 192 | printf '│  %s' "$host" 193 | 194 | # fix this mess later, for now it works 195 | # 196 | # SC: "i is unused" 197 | # shellcheck disable=2034 198 | for i in _ _ $(seq $(($1 - ${#host}))) ; do 199 | printf ' ' 200 | done 201 | 202 | printf '%s\n' '│' 203 | } 204 | 205 | pr_str() { 206 | # print emoji 207 | printf '│ %s ' "$1" 208 | printf "%s" "$2" 209 | 210 | # print str 211 | # print spaces to fit $length 212 | space_needed=$(( length - ${#2} + 2 )) 213 | 214 | # This symbol counts as "2" chars... 215 | # Bizarre. Look into why later. 216 | case $2 in 217 | *''*) 218 | space_needed=$((space_needed + 2)) 219 | esac 220 | 221 | # shellcheck disable=2034 222 | for i in $(seq $space_needed) ; do 223 | printf ' ' 224 | done 225 | 226 | # close and newline 227 | printf '│\n' 228 | } 229 | 230 | get_length() { 231 | host=$(hostname) 232 | host_len=$((5 + ${#USER} + 1 + ${#host})) 233 | if [ ${#model} -ge $host_len ] ; then 234 | echo ${#model} 235 | else 236 | echo $host_len 237 | fi 238 | } 239 | 240 | get_packages() { 241 | case $(os) in 242 | Gentoo*) 243 | qlist -I | wc -l 244 | ;; 245 | OpenBSD*) 246 | pkg_info -l | wc -l 247 | ;; 248 | Fedora*) 249 | dnf list installed 2>/dev/null | wc -l 250 | esac 251 | } 252 | 253 | get_wm() { 254 | for i in i3 dwm openbox fvwm icewm xfwm fluxbox kwin \ 255 | budgie pantheon xmonad Hyprland hyprland sway river gnome ; do 256 | if pgrep $i >/dev/null ; then 257 | echo $i 258 | return 259 | fi 260 | done 261 | 262 | echo "unknown" 263 | } 264 | 265 | get_loadavg() { 266 | if [ -e /proc/loadavg ] ; then 267 | read -r _load < /proc/loadavg 268 | # shellcheck disable=2086 269 | set -- $_load 270 | printf "%s %s %s\n" "$1" "$2" "$3" 271 | else 272 | echo 'unknown' 273 | fi 274 | } 275 | 276 | get_cpu() { 277 | # intel for now 278 | if [ -e /proc/cpuinfo ] ; then 279 | cpu=$(grep 'model name' /proc/cpuinfo) 280 | cpu=${cpu##*\) } 281 | cpu=${cpu%% CPU \@*} 282 | 283 | if [ ! "$cpu" ] ; then 284 | case $(model) in 285 | *"M1 Pro"*) 286 | cpu="Apple M1 Pro $(nproc)-Core" 287 | ;; 288 | *"M1"*) 289 | cpu="Apple M1 $(nproc)-Core" 290 | ;; 291 | esac 292 | fi 293 | 294 | 295 | printf '%s\n' "$cpu" 296 | else 297 | echo 'unknown' 298 | fi 299 | } 300 | 301 | get_term() { 302 | # shellcheck disable=2046 303 | pid2name $(getppid $(getppid $$)) 304 | } 305 | 306 | get_storage() { 307 | if command -v zpool >/dev/null ; then 308 | if zpool list | grep rpool >/dev/null ; then 309 | zpool list | grep rpool | \ 310 | while read -r pool total used remaining _ _ frag perc_used _ ; do 311 | printf '%s/%s (%s)\n' "$used" "$total" "$perc_used" 312 | done 313 | else 314 | >&2 echo "can't find root zfs pool, is it not named rpool?" 315 | fi 316 | else 317 | # >&2 echo "non-zfs not implemented yet" 318 | : 319 | fi 320 | } 321 | 322 | get_toolchain() { 323 | gcc -dumpmachine 324 | } 325 | 326 | get_font() { 327 | case $(get_term) in 328 | kitty) 329 | file="${XDG_CONFIG_HOME:-${HOME}/.config}/kitty/kitty.conf" 330 | if [ -e "$file" ] ; then 331 | font=$(grep -E '^font_family ' "$file") 332 | font=${font#font_family } 333 | # remove any nerd font mentions / cleanup 334 | font=${font% Nerd Font*} 335 | printf '%s\n' "$font" 336 | else 337 | echo "Unknown" 338 | fi 339 | ;; 340 | *) 341 | echo "Unknown Term" 342 | esac 343 | } 344 | 345 | model=$(model) 346 | os=$(os) 347 | pkgs=$(get_packages) 348 | temp=$(get_temp) 349 | mem=$(mem) 350 | shell=${SHELL##*/} 351 | wm=$(get_wm) 352 | length=$(get_length) 353 | loadavg=$(get_loadavg) 354 | cpu=$(get_cpu) 355 | term=$(get_term) 356 | storage=$(get_storage) 357 | toolchain=$(get_toolchain) 358 | font=$(get_font) 359 | 360 | # print top borders 361 | pr_line ┌ ┐ "$length" 362 | pr_host "$length" 363 | pr_line ├ ┤ "$length" 364 | 365 | case $(uname) in 366 | OpenBSD) 367 | emoji=🐡 368 | ;; 369 | *BSD) 370 | emoji= 371 | ;; 372 | Linux) 373 | case $(os) in 374 | Gentoo*) emoji= ;; 375 | Ubuntu*) emoji= ;; 376 | Fedora*) emoji= ;; 377 | *) emoji= 378 | esac 379 | esac 380 | 381 | # print content 382 | pr_str "󰹑" "$model" 383 | pr_str "$emoji" "$os" 384 | pr_str "" "$toolchain" 385 | pr_str "" "$pkgs" 386 | pr_str "" "$wm" 387 | pr_str "" "$term" 388 | pr_str "" "$shell" 389 | pr_str "" "$font" 390 | pr_str "" "$cpu" 391 | pr_str "" "$mem" 392 | pr_str "" "$storage" 393 | pr_str "" "$loadavg" 394 | pr_str "" "$temp" 395 | pr_space 396 | 397 | # print bottom borders 398 | pr_line └ ┘ "$length" 399 | -------------------------------------------------------------------------------- /bin/ffmpeg-concat: -------------------------------------------------------------------------------- 1 | #!/bin/sh -e 2 | # 3 | # http://github.com/mitchweaver 4 | # 5 | # concatenate all given video files into one 6 | # 7 | 8 | usage() { 9 | >&2 printf 'Usage: %s [files]\n' "${0##*/}" 10 | exit 1 11 | } 12 | 13 | [ "$1" ] || usage 14 | for i in "$@" ; do 15 | [ -f "$i" ] || usage 16 | done 17 | 18 | tmp=input.txt 19 | trap 'rm "$tmp" 2>/dev/null ||:' EXIT INT TERM 20 | :>"$tmp" 21 | 22 | for i in "$@" ; do 23 | printf 'file %s\n' "$i" >>"$tmp" 24 | done 25 | 26 | exec ffmpeg \ 27 | -safe 0 \ 28 | -f concat \ 29 | -i "$tmp" \ 30 | -codec copy \ 31 | output."${1##*.}" 32 | -------------------------------------------------------------------------------- /bin/fg: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # http://github.com/mitchweaver/bin 4 | # 5 | # "find-grep", greps for files in all dirs recursing $1 6 | # prints out names of files with matches 7 | # 8 | # when no directory is specified, $PWD is used 9 | # 10 | # notice: Come to attention that "fg" by default in posix is 11 | # 'foreground' but I never use that command. 12 | # After years of having this alias, I'm not changing it ;) 13 | # 14 | # ----------------------------------------------------- 15 | 16 | die() { 17 | >&2 printf '%s\n' "$1" 18 | exit 1 19 | } 20 | 21 | usage() { 22 | die 'Usage: fg [dir] [search terms]' 23 | } 24 | 25 | case $# in 26 | 0) 27 | usage 28 | ;; 29 | 1) 30 | set -- . "$1" 31 | ;; 32 | esac; 33 | 34 | case $1 in 35 | -h|--help) 36 | usage 37 | ;; 38 | *) 39 | [ -d "$1" ] || die "Not a directory: '$1'" 40 | find "$1" -type f 2> /dev/null | while read -r f; do 41 | grep -H -i -- "$2" "$f" 42 | done 43 | ;; 44 | esac 45 | 46 | -------------------------------------------------------------------------------- /bin/fullpath: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # http://github.com/mitchweaver 4 | # 5 | # echos full filepath of given file/folder 6 | # 7 | 8 | if [ -e "$1" ] ; then 9 | case $1 in 10 | *'/'*) 11 | # we probably were already given a full path 12 | ;; 13 | *) 14 | printf '%s/%s\n' "$PWD" "$1" 15 | esac 16 | fi 17 | -------------------------------------------------------------------------------- /bin/getparent: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # https://github.com/mitchweaver 4 | # 5 | # print the parent process name of a given pid 6 | # 7 | 8 | usage() { 9 | >&2 echo 'Usage: getparent [pid]' 10 | exit 1 11 | } 12 | 13 | case $1 in 14 | -h|--help) 15 | usage 16 | esac 17 | 18 | [ "$1" ] || usage 19 | 20 | if ! ps -p "$1" 2>/dev/null ; then 21 | return 1 22 | fi 23 | ps -p "$1" -o ppid= 24 | 25 | exit $? 26 | -------------------------------------------------------------------------------- /bin/getppid: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # http://github.com/mitchweaver/bin 4 | # 5 | # gets the parent pid of given pid 6 | # 7 | 8 | if [ -e "/proc/${1:-$PPID}/status" ] ; then 9 | while read -r line ; do 10 | case $line in 11 | *PPid:*) 12 | printf '%s\n' "${line#PPid:}" 13 | break 14 | esac 15 | done < "/proc/${1:-$PPID}/status" 16 | fi 17 | -------------------------------------------------------------------------------- /bin/gifify: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # http://github.com/mitchweaver/bin 4 | # 5 | # convert a video to gif 6 | # 7 | 8 | [ -f "$1" ] || exit 1 9 | 10 | ffmpeg -i "$1" \ 11 | -filter_complex "[0:v] fps=10,scale=720:-1,split [a][b];[a] palettegen [p];[b][p] paletteuse" \ 12 | output.gif 13 | -------------------------------------------------------------------------------- /bin/gud: -------------------------------------------------------------------------------- 1 | #!/bin/sh -e 2 | # 3 | # http://github.com/mitchweaver/bin 4 | # 5 | # git-gud: the most awesomest git wrapper 6 | # 7 | 8 | die() { >&2 printf '%s\n' "$*" ; exit 1 ; } 9 | noargs='No arguments.' 10 | confirm='Are you sure? (y\n) ' 11 | abort='Aborting.' 12 | 13 | usage() { 14 | >&2 cat < [mandatory] 18 | ------------ 19 | -a add 20 | -m commit [message] 21 | -o push 22 | -u add+commit+push [message] 23 | -p pull changes 24 | -c clone a repo [url] 25 | -gh clone a github repo [user/repo] 26 | -un list untracked files 27 | -d git diff 28 | -l show git log 29 | -b list branches [branch] 30 | -k checkout branch [branch] 31 | -bc create branch [branch] 32 | -bd delete a branch [branch] 33 | -rm remove a file 34 | -mv move a file 35 | -f fetch 36 | -i initialize a repository 37 | -r add a remote 38 | -rv list remotes 39 | -base rebase [num] 40 | -bort abort rebase in progress 41 | -reset hard reset a repo [num] 42 | -cont show repo contributors 43 | EOF 44 | exit 1 45 | } 46 | 47 | # -*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-* 48 | # we solved racism! 49 | # 50 | # returns whether a git repo is using "main" or "master" 51 | # needed due to pointless syntax change in 2020 52 | # -*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-* 53 | main_or_master() { 54 | # shellcheck disable=1007 55 | if PAGER= git branch | grep '\* master' >/dev/null ; then 56 | echo master 57 | elif PAGER= git branch | grep '\* main' >/dev/null ; then 58 | echo main 59 | fi 60 | } 61 | 62 | 63 | main() { 64 | [ "$1" = -h ] && usage 65 | 66 | case $1 in 67 | -c|-gh|-cssh) ;; 68 | *) git status >/dev/null 2>&1 || usage 69 | esac 70 | 71 | # shellcheck disable=1007 72 | case $1 in 73 | -a) shift ; gadd "$@" ;; 74 | -m) shift ; gmit "$@" ;; 75 | -o) shift ; gout "$@" ;; 76 | -of) shift ; gout --force "$@" ;; 77 | -u) shift ; gup "$@" ;; 78 | -c) shift ; git clone "$@" ;; 79 | -cssh) shift ; sshclone "$@" ;; 80 | -p) shift ; gpull "$@" ;; 81 | -pf) shift ; gpull --force "$@" ;; 82 | -k) shift ; git checkout "$@" ;; 83 | -b) shift ; PAGER= git branch "$@" ;; 84 | -bc) shift ; git branch "$@" ;; 85 | -bd) shift ; branchdel "$@" ;; 86 | -d) shift ; gdiff "$@" ;; 87 | -l) shift ; git log --source "$@" ;; 88 | -f) shift ; git fetch "$@" ;; 89 | -i) shift ; git init "$@" ;; 90 | -mv) shift ; git mv "$@" ;; 91 | -rm) shift ; git rm "$@" ;; 92 | -r) shift ; git remote add "$@" ;; 93 | -rv) shift ; git remote -v "$@" ;; 94 | -base) shift ; gbase "$@" ;; 95 | -bort) shift ; git rebase --abort "$@" ;; 96 | -reset) shift ; greset "$@" ;; 97 | -gh) shift ; git clone http://github.com/"$*" ;; 98 | -un) git ls-files --others --exclude-standard ;; 99 | -cont) git log --format="%aN" | sort | \ 100 | uniq -c | sort -nr | sed 's|^[ ]*[^ ]*[ ]*||' ;; 101 | *) git status -bs --show-stash 102 | esac 103 | } 104 | 105 | # If no args, stage all files, (prompting for confirmation). 106 | # Otherwise stage all arguments. 107 | gadd() { 108 | if [ "$1" ] ; then 109 | git add "$@" 110 | else 111 | printf "%s\n%s\n%s" "$noargs" \ 112 | 'About to stage all files...' \ 113 | "$confirm" 114 | read -r ans 115 | [ "$ans" = y ] || die $abort 116 | git add -A 117 | fi 118 | } 119 | 120 | # If one argument, commit with message 121 | # Otherwise, stage all arguments but last 122 | # as files and then use last arg as commit message 123 | # Ex: gud -m 'this is the commit message' 124 | # Ex: gud -m file1 file2 file3 'added 3 files' 125 | gmit() { 126 | case $# in 127 | 0) die "$noargs" ;; 128 | 1) ;; 129 | *) while [ $# -ne 1 ] ; do 130 | git add "$1" 131 | shift 132 | done 133 | esac 134 | git commit -m "$1" 135 | } 136 | 137 | # If no arguments, push out to current branch. 138 | # Otherwise, push to given branch. 139 | gout() { 140 | [ "$1" ] || set -- origin "$(git rev-parse --symbolic-full-name --abbrev-ref HEAD)" 141 | [ "$2" ] || set -- origin "$1" 142 | git push -u "$@" 143 | } 144 | 145 | # If no arguments, git pull. 146 | # Otherwise pull from given branch. 147 | gpull() { 148 | [ "$1" ] || set -- origin "$(main_or_master)" 149 | [ "$2" ] || set -- origin "$1" 150 | git pull "$@" 151 | } 152 | 153 | # Interactively rebase current branch $1 number of commits. 154 | gbase() { 155 | [ "$1" ] || die "$noargs" 156 | count=$1 157 | shift 158 | git rebase -i HEAD~"$count" "$@" 159 | } 160 | 161 | # Stage all, commit all, push all to current branch. 162 | # Argument is the commit message. 163 | gup() { 164 | [ "$1" ] || die "$noargs" 165 | printf '%s\n%s' \ 166 | 'About to stage, commit, and push all changes.' \ 167 | "$confirm" 168 | read -r ans 169 | [ "$ans" = y ] || die $abort 170 | git add -A && git commit -m "$*" && gout 171 | } 172 | 173 | # Perform a hard reset of current branch $1 number of commits. 174 | greset() { 175 | [ "$1" ] || die "$noargs" 176 | printf '%s\n%s' "About to 'git reset --hard $1'..." "$confirm" 177 | read -r ans 178 | [ "$ans" = y ] || die $abort 179 | count=$1 180 | shift 181 | git reset --hard HEAD~"$count" "$@" 182 | } 183 | 184 | branchdel() { 185 | printf '%s\n%s' "About to delete branch $1..." "$confirm" 186 | read -r ans 187 | [ "$ans" = y ] || die $abort 188 | git push --delete origin "$1" 189 | } 190 | 191 | # If no arguments, diff repo against remote main. 192 | # Otherwise, diff repo against given remote branch. 193 | gdiff() { 194 | [ "$1" ] || set -- origin "$(main_or_master)" 195 | [ "$2" ] || set -- origin "$1" 196 | git diff "$1"/"$2" 197 | } 198 | 199 | # because i can never remember the syntax for this 200 | sshclone() { 201 | git clone "git@github.com:$1.git" 202 | } 203 | 204 | main "$@" 205 | -------------------------------------------------------------------------------- /bin/human: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # http://github.com/mitchweaver/bin 4 | # 5 | # convert bytes to human readable format 6 | # 7 | # Ex: 8 | # 6579057657 -> '6.1G' 9 | # 562952382 -> '536.8M' 10 | # 11 | 12 | if [ ! "$1" ] ; then 13 | read -r inp 14 | set -- "$inp" 15 | fi 16 | 17 | if [ "$1" -gt 1099511627776 ] ; then 18 | res=$(( $1 * 10 / 1099511627776 )) 19 | pow=T 20 | elif [ "$1" -gt 1073741824 ] ; then 21 | res=$(( $1 * 10 / 1073741824 )) 22 | pow=G 23 | elif [ "$1" -gt 1048576 ] ; then 24 | res=$(( $1 * 10 / 1048576 )) 25 | pow=M 26 | elif [ "$1" -gt 1024 ] ; then 27 | res=$(( $1 * 10 / 1024 )) 28 | pow=K 29 | else 30 | printf '%sB\n' "${1:-0}" 31 | exit 32 | fi 33 | 34 | # shellcheck disable=SC2295 35 | printf "%s$pow\n" "${res%?}.${res#${res%?}}" 36 | -------------------------------------------------------------------------------- /bin/isempty: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # http://github.com/mitchweaver 4 | # 5 | # quick posix way to check if directory is empty 6 | # 7 | # exits 0 if all directories given are indeed empty 8 | # exits 1 if otherwise 9 | # 10 | 11 | for arg in "$@" ; do 12 | # exit in error if file 13 | if [ -f "$arg" ] ; then 14 | exit 1 15 | elif [ -L "$arg" ] ; then 16 | # if is a symlink, check what it points to 17 | # note: this only checks one-link level deep 18 | if [ -d "$(readlink "$arg")" ] ; then 19 | exit 0 20 | else 21 | exit 1 22 | fi 23 | elif [ -d "$arg" ] ; then 24 | : 25 | else 26 | # is not a directory or a link to a directory 27 | exit 1 28 | fi 29 | 30 | # there should be a way to make this be builtins only 31 | # using printf and glob expansions, look into later 32 | if /bin/rmdir "$arg" 2>/dev/null ; then 33 | /bin/mkdir -p "$arg" 34 | exit 0 35 | else 36 | exit 1 37 | fi 38 | done 39 | -------------------------------------------------------------------------------- /bin/isnum: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # http://github.com/mitchweaver/bin 4 | # 5 | # check if a given argument is a number 6 | # 7 | 8 | case $1 in 9 | ''|*[!0-9]*) 10 | exit 1 11 | ;; 12 | *) 13 | exit 0 14 | esac 15 | -------------------------------------------------------------------------------- /bin/last: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # http://github.com/mitchweaver 4 | # 5 | # "last" implementation for Linux from networking equipment vendor OS's 6 | # (JunOS, Cisco IOS, Nokia TiMOS, etc) 7 | # 8 | # ----------------------------------------------------------------- 9 | 10 | usage() { 11 | >&2 cat <<"EOF" 12 | Print last number of lines from piped output 13 | 14 | Equivalent to tail -n [num]. 15 | Defaults to 5 lines. 16 | 17 | Usage: | last [num] 18 | EOF 19 | exit 1 20 | } 21 | 22 | case $# in 23 | 0|1) 24 | ;; 25 | *) 26 | usage 27 | esac 28 | 29 | NUM= 30 | 31 | if [ "$1" ] ; then 32 | case $1 in 33 | -h|--help) 34 | usage 35 | ;; 36 | *) 37 | isnum "$1" || usage 38 | NUM=$1 39 | esac 40 | else 41 | NUM=5 42 | fi 43 | 44 | tail -n "$NUM" 45 | 46 | -------------------------------------------------------------------------------- /bin/lorem: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # http://github.com/mitchweaver 4 | # 5 | # generate placeholder text 6 | # 7 | 8 | cat <<"EOF" 9 | Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec id mauris quis elit euismod dictum. Phasellus ultrices a ipsum ac efficitur. Mauris est enim, pharetra ac diam in, vulputate dapibus ex. Vestibulum fringilla quam non vulputate scelerisque. Cras sit amet justo metus. Vestibulum ex risus, ullamcorper in velit id, sodales fermentum ipsum. Etiam consectetur lorem leo, sed varius tellus facilisis sed. Sed pretium cursus quam, vel faucibus elit consequat et. Suspendisse ullamcorper ullamcorper finibus. Aenean pretium dolor non varius convallis. Vestibulum euismod dignissim ligula, sit amet vestibulum nisl egestas sit amet. Nunc suscipit, nisi a mattis laoreet, tellus risus porttitor mi, in scelerisque neque nibh at tortor. Duis non varius magna, vel egestas leo. 10 | 11 | Morbi ullamcorper vitae est sit amet semper. Donec imperdiet accumsan viverra. Duis fringilla bibendum enim. Ut blandit purus in libero pellentesque, varius tempus lectus congue. Integer elementum purus eget bibendum porta. Praesent vitae elit eros. Proin sed sapien quis dolor ornare posuere. 12 | 13 | Vestibulum et volutpat velit. Sed sem est, facilisis id leo non, feugiat dapibus elit. Praesent interdum commodo ante, non tincidunt erat sollicitudin vel. Etiam a magna nec orci molestie elementum. Nam et ultrices velit. Mauris mattis dignissim commodo. Sed nisl lacus, rutrum in consectetur ac, cursus non orci. 14 | 15 | Aliquam libero libero, scelerisque non ultrices a, varius vel lectus. Pellentesque fermentum eros erat, quis luctus tortor efficitur at. Nam volutpat lectus vel tristique viverra. Mauris tristique congue vestibulum. In hac habitasse platea dictumst. Morbi pharetra ultricies felis, ut sodales nunc lacinia vel. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Sed dignissim neque nec orci molestie feugiat. Fusce quis sem et diam convallis lacinia. 16 | 17 | Nulla molestie velit massa, vel ultricies leo mollis a. Suspendisse a risus a justo convallis volutpat sit amet quis dolor. Proin ut imperdiet velit. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Donec vel tortor eget ex ultricies condimentum sit amet sed erat. Suspendisse potenti. Maecenas rutrum ante id luctus dapibus. Nulla nunc enim, volutpat non urna et, condimentum venenatis neque. Donec finibus, dui cursus blandit euismod, libero lectus tempus dui, et vehicula enim turpis ut odio. Donec ut congue enim, ut pretium dui. Donec condimentum auctor dolor. Pellentesque vitae nunc sed elit condimentum aliquet. Aliquam egestas, leo porta elementum vehicula, sapien eros hendrerit erat, a ultrices felis erat et ipsum. Vivamus faucibus tristique nisl in finibus. 18 | 19 | Praesent sodales dignissim velit a facilisis. Cras lobortis consequat feugiat. Morbi bibendum pulvinar sem, nec aliquet augue. Maecenas in tincidunt lectus. Nulla eget urna a tortor ultricies vestibulum quis eu odio. Nullam luctus leo libero, vel tincidunt tellus aliquam vel. Nam pretium erat sed faucibus aliquet. 20 | 21 | Maecenas interdum ullamcorper odio, sed ultrices tellus volutpat sed. Vestibulum ut lacinia magna, imperdiet molestie risus. Nam laoreet elementum tristique. Fusce pharetra cursus sapien, nec viverra dui dapibus non. Quisque mollis imperdiet elit, vel malesuada dolor malesuada vel. Duis eu elementum neque. Nam interdum, dolor vestibulum iaculis imperdiet, sapien nibh vestibulum nibh, ut egestas risus nisi vitae turpis. Aenean et aliquam purus, quis imperdiet mauris. Vivamus sit amet dolor non ex consectetur porttitor vel a lectus. Donec fringilla est enim, vel tempor lorem feugiat in. Integer sem dui, efficitur id finibus ac, venenatis hendrerit arcu. Ut mollis mi ut ultricies facilisis. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. 22 | 23 | Curabitur lobortis sollicitudin augue. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Sed condimentum ac dui nec maximus. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Phasellus luctus risus a libero ornare, ac porttitor sem fringilla. Proin sed metus hendrerit, tempus est sed, hendrerit ipsum. Praesent efficitur mattis tortor, at luctus nibh ultricies sit amet. Mauris in orci id turpis porttitor egestas. Pellentesque mattis neque non lorem laoreet, id viverra eros posuere. Aenean interdum enim ut ante pellentesque, a bibendum erat sollicitudin. Curabitur eget felis maximus, maximus erat ut, aliquam turpis. Sed blandit eget felis sit amet semper. Vestibulum pretium nunc sit amet varius placerat. Ut tincidunt turpis vel massa tincidunt tincidunt eget at nunc. 24 | 25 | Fusce at dolor eu arcu volutpat auctor ac quis dui. Vivamus laoreet lobortis lectus. Suspendisse aliquet nunc vitae urna aliquam varius. Nulla massa leo, porttitor eget leo rhoncus, dictum aliquam risus. Aenean faucibus ipsum laoreet, dignissim mauris vel, feugiat nisi. Integer vitae eros eu dolor blandit condimentum. Nunc et eros sit amet risus pretium placerat. 26 | 27 | Morbi eu dapibus ligula, a iaculis tellus. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia curae; Fusce odio urna, vehicula eget purus in, ullamcorper sodales mauris. Mauris consectetur tempor metus, faucibus feugiat eros eleifend vitae. Pellentesque pellentesque turpis eu feugiat vehicula. Aenean dolor est, auctor vitae erat quis, lacinia hendrerit ante. Phasellus non tincidunt odio, at convallis risus. 28 | EOF 29 | -------------------------------------------------------------------------------- /bin/mpvimg: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # http://github.com/mitchweaver/bin 4 | # 5 | # use mpv as an image viewer 6 | # 7 | 8 | [ "$1" = -- ] && shift 9 | 10 | launch() { 11 | exec mpv \ 12 | --no-config \ 13 | --hwdec=auto-safe \ 14 | --really-quiet \ 15 | --no-keepaspect \ 16 | --ontop \ 17 | --pause \ 18 | --loop \ 19 | --osd-level=0 \ 20 | --hwdec=auto-safe \ 21 | --autofit-larger=80%x70% \ 22 | --autofit-smaller=10%x10% \ 23 | --no-audio \ 24 | --no-terminal \ 25 | --x11-name=mpvimg \ 26 | --title="${1##*/}" \ 27 | -- "$1" 28 | } 29 | 30 | for image in "$@" ; do 31 | if [ -f "$image" ] ; then 32 | launch "$image" 33 | else 34 | url=$(printf '%s\n' "$image" | urls >/dev/null) 35 | if [ -n "$url" ] ; then 36 | launch "$url" 37 | else 38 | >&2 printf 'Error: "%s" does not exist.\n' "$1" 39 | exit 1 40 | fi 41 | fi 42 | done 43 | -------------------------------------------------------------------------------- /bin/nuke-iptables: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # https://github.com/mitchweaver 4 | # 5 | # ever bork your iptable config and need 6 | # to rule out it being the problem? 7 | # 8 | 9 | ip6tables --policy INPUT ACCEPT; 10 | ip6tables --policy OUTPUT ACCEPT; 11 | ip6tables --policy FORWARD ACCEPT; 12 | 13 | ip6tables -Z; # zero counters 14 | ip6tables -F; # flush rules 15 | ip6tables -X; # delete all chains 16 | 17 | iptables --policy INPUT ACCEPT; 18 | iptables --policy OUTPUT ACCEPT; 19 | iptables --policy FORWARD ACCEPT; 20 | 21 | iptables -Z; # zero counters 22 | iptables -F; # flush rules 23 | iptables -X; # delete all chains 24 | -------------------------------------------------------------------------------- /bin/opn: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # http://github.com/mitchweaver/bin 4 | # 5 | # ___ _____ ___ 6 | # / __`\/\ '__`\/' _ `\ 7 | # /\ \L\ \ \ \L\ /\ \/\ \ 8 | # \ \____/\ \ ,__\ \_\ \_\ 9 | # \/___/ \ \ \/ \/_/\/_/ 10 | # \ \_\ 11 | # \/_/ 12 | # 13 | # yet another plumber script 14 | # 15 | # -/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/- 16 | 17 | usage() { 18 | head -n 11 "$0" | tail -n 7 19 | cat </dev/null 2>&1 & 87 | } 88 | 89 | 90 | isfile() { 91 | case $(printf '%s' "${1##*.}" | tr '[:upper:]' '[:lower:]') in 92 | mp4|mov|webm|gif|mkv|avi) isvideo "$1" ;; 93 | jpg|jpeg|png) isimage "$@" ;; 94 | mp3|flac|ogg|opus|wav) launch play "$@" ;; 95 | pdf|epub) ispdf "$@" ;; 96 | docx|rtf|odt|ods|pptx|xlsx|csv) launch libreoffice "$1" ;; 97 | xcf) launch gimp "$1" ;; 98 | xoj) launch xournal "$1" ;; 99 | pcap) launch wireshark "$1" ;; 100 | svg) launch display "$1" ;; 101 | openshot|osp) launch openshot-qt "$1" ;; 102 | link) 103 | read -r url < "$1" 104 | if [ "$url" ] ; then 105 | isurl "$url" 106 | fi 107 | ;; 108 | *) 109 | case $(file -L "$1") in 110 | *ASCII*|*Unicode*|*'shell script'*|*': empty'|*text) 111 | edit "$1" 112 | ;; 113 | 'broken symbolic link') 114 | >&2 printf "Broken symbolic link: %s\n" "$1" 115 | return 1 116 | ;; 117 | *) 118 | >&2 printf 'Unable to determine file type: %s\n' "$1" 119 | return 1 120 | esac 121 | esac 122 | } 123 | 124 | isdir() { 125 | if command -v eza >/dev/null ; then 126 | eza -F --group-directories-first "$1" 127 | else 128 | ls -F "$1" 129 | fi 130 | } 131 | 132 | isurl() { 133 | # if it is a remote file, handle it via extension 134 | case ${1##*.} in 135 | zip|gz|bz2|xz|tgz|tar|rar|7z|pdf|epub) exec dl "$*" ;; 136 | mp4|webm|gif|mkv|avi|flv|mov) isvideo "$*" ;; 137 | mp3|flac|wav|ogg|opus|aac) play "$*" ;; 138 | jpg|png|jpeg|JPG|JPEG) isimage "$*" 139 | esac 140 | 141 | case $1 in 142 | *tube*|*tu.be*|*invidio*|*vimeo*|*v.redd*|*hub.*|*//v.*.com/*) 143 | isvideo "$@" 144 | ;; 145 | *bandcamp*|*soundcloud*) 146 | launch firefox "$@" 147 | ;; 148 | *i.redd*|*//i.*.com/*) 149 | isimage "$@" 150 | ;; 151 | ftp://*) 152 | exec dl "$@" 153 | ;; 154 | *) 155 | # exhausted all checks, it must just be 156 | # a web page to be viewed in a browser 157 | launch firefox "$@" 158 | esac 159 | } 160 | 161 | edit() { 162 | case ${EDITOR:-vi} in 163 | # see if we are using a console editor 164 | # if so, we may need to open a terminal 165 | nvim|vim|vi|nano|micro) 166 | ps -p $$ -o ppid= | { 167 | read -r ppid 168 | case $(ps -p "$ppid" -o command=) in 169 | "${SHELL##*/}"|*"/${SHELL##*/}") 170 | # if attached to a terminal emulator, just open the editor 171 | # shellcheck disable=2086 172 | exec ${EDITOR:-vi} -- "$*" 173 | ;; 174 | *) 175 | # if not called from a terminal, open one to edit 176 | # shellcheck disable=2086 177 | if command -v kitty >/dev/null ; then 178 | launch kitty --detach --single-instance ${EDITOR:-vi} -- "$*" 179 | elif command -v st >/dev/null ; then 180 | st -e ${EDITOR:-vi} -- "$*" 181 | else 182 | launch ${TERMINAL_PROG:-xterm} -e ${EDITOR:-vi} -- "$*" 183 | fi 184 | esac 185 | } 186 | ;; 187 | *) 188 | # otherwise we have a gui editor, just launch it 189 | # shellcheck disable=2086 190 | launch ${EDITOR:-vi} -- "$*" & 191 | esac 192 | } 193 | 194 | # mpv errors if its options are one string 195 | isvideo() { 196 | case ${1##*.} in 197 | gif|webm) 198 | MPV_OPTS="$MPV_OPTS --loop" 199 | esac 200 | 201 | # shellcheck disable=2086 202 | # launch mpv $MPV_OPTS -- "$*" 203 | # shellcheck disable=2086 204 | launch celleloid --new-window $MPV_OPTS -- "$*" 205 | } 206 | 207 | isimage() { 208 | launch mpvimg "$*" 209 | } 210 | 211 | ispdf() { 212 | if command -v zathura >/dev/null ; then 213 | launch zathura "$@" 214 | elif command -v mupdf >/dev/null ; then 215 | launch mupdf "$@" 216 | fi 217 | } 218 | 219 | 220 | # -*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-* 221 | # End Functions 222 | # -*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-* 223 | 224 | if [ -f "$1" ] ; then 225 | isfile "$@" 226 | elif [ -d "$1" ] ; then 227 | isdir "$@" 228 | else 229 | # remove any given white space 230 | # note: trim can also be found at https://github.com/mitchweaver/bin 231 | set -- "$(printf '%s\n' "$*" | trim)" 232 | 233 | case $1 in 234 | http://*|https://*|ftp://*|*.com|*.org|*.net) 235 | isurl "$@" 236 | ;; 237 | # youtube, but shorthand to indicate only play audio 238 | *'m:watch?v='*) 239 | play https://youtube.com/"${1#m:}" 240 | ;; 241 | # youtube video 242 | *'watch?v='*) 243 | isvideo https://youtube.com/"$1" 244 | ;; 245 | # wikipedia 246 | *'wiki/'*) 247 | lanuch firefox "https://en.wikipedia.org/$1" 248 | ;; 249 | # subreddit 250 | 'r '*|/r/*|r/*) 251 | set -- "${1#'r '}" 252 | set -- "${1#r/}" 253 | set -- "${1#/r/}" 254 | launch firefox "https://old.reddit.com/r/$1" 255 | ;; 256 | # usps tracking number - either 22 digits long starting with '940', 257 | # or 26 digits long starting with '920' 258 | 940*|920*) 259 | case ${#1} in 260 | 22|26) 261 | launch firefox "https://tools.usps.com/go/TrackConfirmAction?qtc_tLabels1=$1" 262 | esac 263 | ;; 264 | *bandcamp*|*soundcloud*) 265 | play https://"$1" 266 | ;; 267 | imbd/*) 268 | isurl https://imdb.com/"$1" 269 | ;; 270 | *.com/*|*.org/*) 271 | launch firefox http://"$1" 272 | ;; 273 | # github - note: this rule is vague so it must be at the bottom 274 | */*) 275 | launch firefox "https://github.com/$1" 276 | ;; 277 | *) 278 | case ${#1} in 279 | # 40 chars, could be a sha256, check if git commit 280 | 40) 281 | isurl "https://github.com/search?q=$1&type=Commits" 282 | ;; 283 | *) 284 | >&2 printf "Couldn't plumb %s\n" "$1" 285 | exit 1 286 | esac 287 | esac 288 | fi 289 | -------------------------------------------------------------------------------- /bin/pack: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # http://github.com/mitchweaver/bin 4 | # 5 | # archive things 6 | # 7 | # shellcheck disable=2181 8 | # ======================================================================== 9 | 10 | usage() { 11 | >&2 printf 'Usage: %s [-n no remove] [-xz] [-lz4] \n' "${0##*/}" 12 | exit 1 13 | } 14 | 15 | while [ "$1" ] ; do 16 | case ${1#-} in 17 | lz4) 18 | ALGO=lz4 19 | shift 20 | ;; 21 | xz) 22 | ALGO=xz 23 | shift 24 | ;; 25 | n) 26 | NO_REMOVE=true 27 | shift 28 | ;; 29 | *) 30 | # is a folder 31 | break 32 | esac 33 | done 34 | 35 | [ -d "$1" ] || usage 36 | 37 | # safely exit if given root :^) 38 | [ "$1" = / ] && exit 1 39 | 40 | : "${ALGO:=xz}" 41 | out="${1%/}".tar.$ALGO 42 | 43 | if [ -f "$out" ] ; then 44 | printf "file '%s' already exists, overwrite? (y/n): " "$out" 45 | read -r ans 46 | [ "$ans" = y ] || exit 1 47 | fi 48 | 49 | # note: lz4 default is -1, with the --best being -12 50 | # seems -6 is a happy medium where it compresses 51 | # reasonably well but doesn't take forever 52 | # (speed is the whole point of lz4 anyway) 53 | case $ALGO in 54 | xz) tar -cvf - "$1" | xz -qcT 0 > "$out" ;; 55 | lz4) tar -cvf - "$1" | lz4 -q -6 > "$out" 56 | esac 57 | 58 | [ $? -eq 0 ] || exit 1 59 | 60 | if [ ! "$NO_REMOVE" ] ; then 61 | rm -r "$1" 62 | fi 63 | -------------------------------------------------------------------------------- /bin/pad: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # http://github.com/mitchweaver 4 | # 5 | # temp file scratch pad 6 | # 7 | 8 | mkdir -p /tmp/$$.tmpsh 9 | trap '/bin/rm -rf -- /tmp/$$.tmpsh' EXIT INT TERM HUP 10 | cd /tmp/$$.tmpsh && 11 | ${EDITOR:-vi} $$.md && 12 | cd - >/dev/null && 13 | { /bin/rm -rf -- /tmp/$$.tmpsh 2>/dev/null ||: ; } 14 | -------------------------------------------------------------------------------- /bin/pid2name: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # http://github.com/mitchweaver 4 | # 5 | # print out corresponding process names from given pids 6 | # 7 | # silently ignores pids it can't find 8 | # 9 | 10 | usage() { 11 | >&2 printf 'Usage: echo 0 | %s\n' "${0##*/}" 12 | exit 1 13 | } 14 | 15 | getname() { 16 | ps --no-headers -p "$1" -o cmd= 2>/dev/null | \ 17 | while read -r name _ ; do 18 | # print only the process name, not full path 19 | printf '%s\n' "${name##*/}" 20 | done 21 | } 22 | 23 | if [ "$1" ] ; then 24 | case $1 in 25 | -h|--help) 26 | usage 27 | esac 28 | # assume we're given pids as argument then 29 | for pid in "$@" ; do 30 | getname "$pid" 31 | done 32 | else 33 | # we are given piped input 34 | while read -r pid ; do 35 | getname "$pid" 36 | done 37 | fi 38 | -------------------------------------------------------------------------------- /bin/png2jpg: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # https://github.com/mitchweaver/bin 4 | # 5 | # batch convert png to jpg and strip metadata 6 | # works given arguments or piped filenames 7 | # 8 | # note: mangles spaces, fix later 9 | # 10 | 11 | if [ ! "$1" ] && [ -p /dev/stdin ] ; then 12 | # fix later... 13 | # shellcheck disable=2046 14 | set -- $(cat) 15 | fi 16 | 17 | for file in "$@" ; do 18 | [ -f "$file" ] || continue 19 | 20 | printf '[*] PROCESSING: %s\n' "$file" 21 | 22 | case $file in 23 | *.png) 24 | convert "$file" "${file%png}"jpg && 25 | jpegoptim -s "${file%png}"jpg && 26 | rm "$file" 27 | ;; 28 | *) 29 | >&2 printf 'Not a PNG file: %s\n' "$file" 30 | esac 31 | done 32 | -------------------------------------------------------------------------------- /bin/proxmox-ram-provisioned: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # https://github.com/mitchweaver/bin 4 | # 5 | # tool to get a nice overview of RAM provisioned 6 | # for all VMs/containers on your proxmox server 7 | # 8 | # ------------------------------------------------ 9 | 10 | 11 | # keep a running total of bytes provisioned 12 | TOTAL=0 13 | 14 | # convert bytes to human readable format 15 | human() { 16 | if [ "$1" -gt 1099511627776 ] ; then 17 | res=$(( $1 * 10 / 1099511627776 )) 18 | pow=T 19 | elif [ "$1" -gt 1073741824 ] ; then 20 | res=$(( $1 * 10 / 1073741824 )) 21 | pow=G 22 | elif [ "$1" -gt 1048576 ] ; then 23 | res=$(( $1 * 10 / 1048576 )) 24 | pow=M 25 | elif [ "$1" -gt 1024 ] ; then 26 | res=$(( $1 * 10 / 1024 )) 27 | pow=K 28 | else 29 | printf '%sB\n' "${1:-0}" 30 | exit 31 | fi 32 | 33 | # shellcheck disable=SC2295 34 | printf "%s$pow\n" "${res%?}.${res#${res%?}}" 35 | } 36 | 37 | 38 | cat <<"EOF" 39 | VIRTUAL MACHINE RAM USAGE: 40 | --------------------------- 41 | EOF 42 | 43 | for file in /etc/pve/qemu-server/*.conf ; do 44 | # get memory in megabytes 45 | mem=$(grep memory: "$file") 46 | mem=${mem#*: } 47 | # convert megabytes to bytes 48 | mem="$((mem * 1024 * 1024))" 49 | TOTAL=$((TOTAL + mem)) 50 | mem=$(human "$mem") 51 | name=$(grep name: "$file") 52 | printf '%s: %s\n' "${name#*: }" "$mem" 53 | done 54 | 55 | cat <<"EOF" 56 | 57 | CONTAINER RAM USAGE: 58 | --------------------------- 59 | EOF 60 | 61 | for file in /etc/pve/lxc/*.conf ; do 62 | # get memory in megabytes 63 | mem=$(grep memory: "$file") 64 | mem=${mem#*: } 65 | # convert megabytes to bytes 66 | mem="$((mem * 1024 * 1024))" 67 | TOTAL=$((TOTAL + mem)) 68 | mem=$(human "$mem") 69 | name=$(grep name: "$file") 70 | printf '%s: %s\n' "${name#*: }" "$mem" 71 | done 72 | 73 | cat <<"EOF" 74 | 75 | TOTAL RAM PROVISIONED: 76 | --------------------------- 77 | EOF 78 | 79 | human "$TOTAL" 80 | -------------------------------------------------------------------------------- /bin/rgen: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # http://github.com/mitchweaver/bin 4 | # 5 | # generate a random string 6 | # 7 | # default: 16 chars 8 | # 9 | 10 | LC_ALL=C \ 11 | tr -dc -- A-Za-z0-9 < /dev/urandom 2>/dev/null | \ 12 | dd ibs=1 obs=1 count="${1:-16}" 2>/dev/null 13 | 14 | # close with new line 15 | echo 16 | -------------------------------------------------------------------------------- /bin/rot13: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # http://github.com/mitchweaver/bin 4 | # 5 | # tr rot13 6 | # 7 | 8 | tr 'A-Za-z' 'N-ZA-Mn-za-m' 9 | -------------------------------------------------------------------------------- /bin/sloc: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # http://github.com/mitchweaver/bin 4 | # 5 | # count lines of code in a shellscript 6 | # ignores comments and blank lines 7 | # 8 | 9 | usage() { 10 | >&2 printf 'Usage: %s [file] or %s < [file]\n' "${0##*/}" "${0##*/}" 11 | exit 1 12 | } 13 | 14 | if [ "$1" ] ; then 15 | case ${1#-} in 16 | h) 17 | usage 18 | ;; 19 | *) 20 | [ -f "$1" ] || usage 21 | esac 22 | 23 | printf '%s' 'SLOC: ' 24 | sed '/^\s*#/d;/^\s*$/d' "$1" | wc -l | sed 's/ //g' 25 | else 26 | printf '%s' 'SLOC: ' 27 | sed '/^\s*#/d;/^\s*$/d' | wc -l | sed 's/ //g' 28 | fi 29 | -------------------------------------------------------------------------------- /bin/steam_renice_daemon.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # shitty script to keep steam games running at highest priority 4 | # 5 | # -20 for nice (highest) 6 | # 1 for ionice (real time) 7 | # 8 | # https://github.com/mitchweaver/bin 9 | # 10 | 11 | if [ "$(id -u)" -ne 0 ] ; then 12 | >&2 echo "Must be run as root." 13 | exit 1 14 | fi 15 | 16 | INTERVAL=$(( 60 * 5 )) 17 | LOGFILE="/tmp/${0##*/}.log" 18 | 19 | while : ; do 20 | pgrep -f steam | \ 21 | while read -r pid ; do 22 | renice -n -20 -p "$pid" && echo "Successfully changed process '$pid' nice to -20" 23 | ionice -c 1 -p "$pid" && echo "Successfully changed process '$pid' ionice to Real Time" 24 | done 25 | sleep "$INTERVAL" 26 | done >> "$LOGFILE" 2>&1 27 | 28 | -------------------------------------------------------------------------------- /bin/tlog: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # http://github.com/mitchweaver/bin 4 | # 5 | # prefix given lines with timestamp 6 | # useful to pipe to from daemons 7 | # 8 | 9 | while read -r line ; do 10 | if [ -n "$line" ] ; then 11 | printf '[%s] %s\n' "$(date +"%Y-%m-%d %H:%M:%S")" "$line" 12 | fi 13 | done 14 | -------------------------------------------------------------------------------- /bin/tmpsh: -------------------------------------------------------------------------------- 1 | #!/bin/sh -ex 2 | # 3 | # http://github.com/mitchweaver/bin 4 | # 5 | # open shell in a temporary dir 6 | # 7 | 8 | dir=/tmp/$$.tmpsh 9 | 10 | mkdir -p "$dir" 11 | trap '/bin/rm -rf -- "${dir:-?}"' EXIT INT TERM HUP 12 | 13 | cd "$dir" 14 | (${SHELL:-/bin/sh}) 15 | -------------------------------------------------------------------------------- /bin/trash: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # http://github.com/mitchweaver 4 | # 5 | # a tiny posix trash can 6 | # 7 | # assumes you also have "d", "rgen", and "human" from my bin in your $PATH 8 | # 9 | # ============================================================ 10 | # ENVIRONMENT SETTINGS: 11 | # ============================================================ 12 | # define objects greater than 4GB as being not trashable 13 | : "${TRASH_MAX_SIZE:="$((1024 * 1024 * 1024 * 4))"}" 14 | : "${TRASH_LOCATION:=${XDG_DATA_HOME:-${HOME}/.local}/share/Trash/files}" 15 | # ============================================================ 16 | 17 | usage() { 18 | cat <&2 printf 'Error: %s\n' "$*" 36 | exit 1 37 | } 38 | 39 | get_size() { 40 | du -bd 0 "$1" | \ 41 | while read -r size _ ; do 42 | echo "$size" 43 | done 44 | } 45 | 46 | dumpster() { 47 | # trim leading slash, if exists 48 | file="${1%/}" 49 | if [ -L "$file" ] ; then 50 | printf 'Found symlink: "%s"  "%s"\n' "$file" "$(readlink "$file")" 51 | if unlink "$file" ; then 52 | msg "Unlinked: $file" 53 | else 54 | die "Failed to unlink: $file" 55 | fi 56 | elif [ -e "$file" ] ; then 57 | if [ -d "$file" ] && [ ! "$RECURSIVE" ] ; then 58 | die "\"$file\" is a folder, did you mean to use [-r]?" 59 | fi 60 | size="$(get_size "$file")" 61 | if [ ! "$size" -gt "$TRASH_MAX_SIZE" ] ; then 62 | if /bin/mv "$file" "$TRASH_LOCATION/${file##*/}-$(rgen 5).trashed" ; then 63 | msg "Trashed: $file" 64 | else 65 | die "Failed to trash: $file" 66 | fi 67 | else 68 | msg "Error: ${file##*/} is too big to trash" 69 | printf 'Would you like to permanently delete it? (y/n): ' 70 | read -r ans 71 | case $ans in 72 | y|yes|Y|YES) 73 | if [ "$file" != / ] ; then 74 | /bin/rm -rfv -- "${file:-?}" 75 | fi 76 | exit $? 77 | ;; 78 | *) 79 | die 'Understood. Not removing.' 80 | esac 81 | fi 82 | else 83 | die "Error: $file does not exist" 84 | fi 85 | } 86 | 87 | take_out_the_trash() { 88 | msg "Trash can: $(get_size "$TRASH_LOCATION" | human)" 89 | >&2 printf '%s' 'Take out the trash? (y/n): ' 90 | read -r ans 91 | if [ "$ans" = y ] ; then 92 | /bin/rm -rfv -- "${TRASH_LOCATION:-?}"/* 93 | find "${TRASH_LOCATION:-?}" -name '.*' ! -name '.' ! -name '..' -exec /bin/rm -rfv -- "{}" \; 94 | >&2 printf '%s\n%s\n' \ 95 | '-----------------------------' \ 96 | 'Emptied.' 97 | else 98 | >&2 echo 'Cancel.' 99 | exit 1 100 | fi 101 | } 102 | 103 | main() { 104 | [ "$1" ] || usage 105 | 106 | for dep in d rgen human ; do 107 | if ! command -v "$dep" >/dev/null ; then 108 | die "Missing dependency: $dep" 109 | fi 110 | done 111 | 112 | mkdir -p "$TRASH_LOCATION" 113 | 114 | unset RECURSIVE 115 | case $1 in 116 | -r|-rf|-fr|r) 117 | RECURSIVE=true 118 | shift 119 | esac 120 | 121 | case "$1" in 122 | -h|h) 123 | usage 124 | ;; 125 | -l|l) 126 | d "${TRASH_LOCATION}" 127 | ;; 128 | -e|e) 129 | take_out_the_trash 130 | ;; 131 | *) 132 | for garbage in "$@" ; do 133 | # ignore mistaken -r,-v,-f gracefully 134 | case $garbage in 135 | -r|-f|-rf|-rfv|-rvf|-fv|-rv) 136 | [ -e "$garbage" ] || continue 137 | esac 138 | dumpster "$garbage" || exit 1 139 | done 140 | esac 141 | } 142 | 143 | main "$@" 144 | -------------------------------------------------------------------------------- /bin/unpack: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # http://github.com/mitchweaver/bin 4 | # 5 | # extract things 6 | # 7 | 8 | usage() { 9 | >&2 printf '%s\n' "Usage: ${0##*/} [-c copy_path] file" 10 | exit 1 11 | } 12 | 13 | decompress() { 14 | case ${1##*.} in 15 | gz|tgz) gunzip -qdc "$1" ;; 16 | xz|txz) xz -qdcT 0 "$1" ;; 17 | bz2|tbz) bunzip2 -qdc "$1" ;; 18 | zst|zstd) zstd -dqc "$1" ;; 19 | lz4) lz4 -dqc "$1" 20 | esac 21 | } 22 | 23 | run() { 24 | case $1 in 25 | *tar.*|*.tgz|*.txz|*.tbz) 26 | decompress "$1" | \ 27 | tar -C "${COPY_PATH:-$PWD}" -xpf - 28 | ;; 29 | *.xz|*.gz|*.bz2|.zstd|.zst|.lz4) 30 | decompress "$1" "${COPY_PATH:-$PWD}/${1%.*}" 31 | ;; 32 | *.zip) 33 | unzip -q "$1" -d "$2" 34 | ;; 35 | *.rar) 36 | unrar x "$1" 37 | ;; 38 | *.7z) 39 | 7z x "$1" 40 | ;; 41 | *.tar) 42 | tar -C "${COPY_PATH:-$PWD}" -xpf "$1" 43 | ;; 44 | *) 45 | >&2 echo "Unrecognized compression format: ${1##*.}" 46 | esac 47 | } 48 | 49 | while [ "$1" ] ; do 50 | case $1 in 51 | -h|h) 52 | usage 53 | ;; 54 | -C|-c) 55 | COPY_PATH=$1 56 | ;; 57 | *) 58 | run "$@" 59 | esac 60 | shift 61 | done 62 | -------------------------------------------------------------------------------- /bin/upl: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # http://github.com/mitchweaver/bin 4 | # 5 | # upload stuff 6 | # 7 | # deps: urls 8 | #------------------------------------------ 9 | 10 | # try to read file path from pipe if no arg 11 | if [ ! "$1" ] ; then 12 | read -r inp 13 | if [ "$inp" ] ;then 14 | set -- "$inp" 15 | else 16 | exit 1 17 | fi 18 | fi 19 | 20 | case $1 in 21 | -u) 22 | TARGET=uguu 23 | shift 24 | ;; 25 | -0) 26 | TARGET=0x0 27 | shift 28 | esac 29 | 30 | # exit if file does not exist 31 | [ -f "$1" ] || exit 1 32 | 33 | case $TARGET in 34 | uguu) 35 | url=$(curl -sF \ 36 | "files[]=@$1" \ 37 | https://uguu.se/upload.php 2>/dev/null | \ 38 | jq -r '.files | .[] | .url') 39 | ;; 40 | 0x0|*) 41 | url=$(curl -sF "file=@$1" https://0x0.st 2>/dev/null) 42 | esac 43 | 44 | if [ "$url" ] ; then 45 | # test that we actually got a url not an error message 46 | if ! printf '%s\n' "$url" | urls >/dev/null 2>&1 ; then 47 | exit 1 48 | fi 49 | 50 | printf '%s\n' "$url" 51 | 52 | # copy into all clipboards for convenience 53 | if command -v xsel >/dev/null ; then 54 | printf '%s\n' "$url" | xsel -ip 55 | printf '%s\n' "$url" | xsel -is 56 | printf '%s\n' "$url" | xsel -ib 57 | fi 58 | else 59 | exit 1 60 | fi 61 | -------------------------------------------------------------------------------- /bin/wayland_or_x11: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # https://github.com/mitchweaver/bin 4 | # 5 | # tries to intelligently determine if a wayland or x11 session exists 6 | # ======================================================================== 7 | 8 | isX() { echo X11 ; exit ; } 9 | isW() { echo wayland ; exit ; } 10 | 11 | # Note: this is often unset for same reason above 12 | # when launching sway from tty 13 | [ -e "$XDG_SESSION_ID" ] && isW 14 | 15 | # sometimes this works, depends on bin names and paths 16 | pgrep -f wayland-session >/dev/null && isW 17 | 18 | # as shitty as this is, seems to be the most effective 19 | # although it doesn't catch DEs that could be either like Gnome 20 | # but, if using Gnome the two cases above should have caught it 21 | 22 | for wm in kwin_wayland sway river Hypr hyprland labwc ; do 23 | pgrep -x $wm >/dev/null && isW 24 | done 25 | 26 | for wm in dwm xmonad i3 openbox ; do 27 | pgrep -x $wm >/dev/null && isX 28 | done 29 | 30 | # Note: not reliable, when starting sway from tty not a DM this reports "tty" 31 | if command -v loginctl >/dev/null ; then 32 | string=$(loginctl show-session "$XDG_SESSION_ID" -p Type) 33 | string=${string#Type=} 34 | case $string in 35 | wayland) 36 | isW 37 | ;; 38 | *) 39 | isX 40 | esac 41 | fi 42 | 43 | # if we're still here, undeterminable 44 | echo UNKNOWN 45 | -------------------------------------------------------------------------------- /bin/webmify: -------------------------------------------------------------------------------- 1 | #!/bin/sh -e 2 | # 3 | # http://github.com/mitchweaver/bin 4 | # 5 | # convert video files to webm 6 | # 7 | 8 | for file ; do 9 | if [ -f "$file" ] ; then 10 | ext=${file##*.} 11 | 12 | # shellcheck disable=SC2295 13 | ffmpeg -i "$1" -y \ 14 | -c:v libvpx -crf 4 -b:v 1500K -vf \ 15 | scale=640:-1 -ac 1 -c:a libvorbis "${file%$ext}webm" 16 | 17 | rm -f "$file" 18 | else 19 | >&2 printf 'No such file: %s\n' "$file" 20 | continue 21 | fi 22 | done 23 | -------------------------------------------------------------------------------- /bin/zfs-nuke-snapshots: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # https://github.com/mitchweaver/bin 4 | # 5 | # quickly loop through deleting all zfs snapshots 6 | # pausing to ask for confirmation 7 | # 8 | # will also NOT prompt for any boot-pool snapshots out of safety 9 | # 10 | # shellcheck disable=2046 11 | # 12 | 13 | 14 | for snapshot in $(zfs list -H -t snapshot | cut -f 1) ; do 15 | [ "$snapshot" ] || break 16 | 17 | case $snapshot in 18 | *boot*) 19 | continue 20 | esac 21 | 22 | printf 'Found snap: %s\nDelete? (y/n):' "$snapshot" 23 | read -r ans 24 | case $ans in 25 | y|Y) 26 | if [ $(id -u) -eq 0 ] ; then 27 | set -x 28 | zfs destroy "$snapshot" 29 | set +x 30 | else 31 | set -x 32 | sudo zfs destroy "$snapshot" 33 | set +x 34 | fi 35 | ;; 36 | *) 37 | printf 'Not deleting. Skipping.\n\n' 38 | esac 39 | unset ans 40 | done 41 | 42 | -------------------------------------------------------------------------------- /check: -------------------------------------------------------------------------------- 1 | #!/bin/sh -e 2 | 3 | # automatically read from .travis.yml 4 | if [ -f .travis.yml ] ; then 5 | while read -r line ; do 6 | case $line in 7 | *shellcheck*) 8 | line=${line##* } 9 | if [ -d "${line%\/\*}" ] ; then 10 | # shellcheck disable=2086 11 | shellcheck -s sh $line 12 | fi 13 | esac 14 | done < .travis.yml 15 | fi 16 | -------------------------------------------------------------------------------- /check.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh -e 2 | 3 | # automatically read from .travis.yml 4 | if [ -f .travis.yml ] ; then 5 | while read -r line ; do 6 | case $line in 7 | *shellcheck*) 8 | line=${line##* } 9 | if [ -d "${line%\/\*}" ] ; then 10 | # shellcheck disable=2086 11 | shellcheck -s sh $line 12 | fi 13 | esac 14 | done < .travis.yml 15 | fi 16 | -------------------------------------------------------------------------------- /etc/init.d/steam_renice_daemon: -------------------------------------------------------------------------------- 1 | #!/sbin/openrc-run 2 | 3 | pidfile="/run/steam_renice_daemon.${instance}.pid" 4 | command="/usr/local/bin/steam_renice_daemon.sh" 5 | command_background="true" 6 | 7 | -------------------------------------------------------------------------------- /legacy/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2020 Mitch Weaver 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all 11 | copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | SOFTWARE. 20 | -------------------------------------------------------------------------------- /legacy/README.md: -------------------------------------------------------------------------------- 1 | # old 2 | 3 | popular scripts that I personally no longer use 4 | keeping here for historical purposes 5 | -------------------------------------------------------------------------------- /legacy/asahi/README.md: -------------------------------------------------------------------------------- 1 | # asahi 2 | 3 | 4 | Linux / Asahi files 5 | 6 | also see https://github.com/mitchweaver/gentoo 7 | 8 | for gentoo install guide and various troubleshooting tips 9 | -------------------------------------------------------------------------------- /legacy/asahi/asahi-brightnessctl: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # https://github.com/mitchweaver/bin 4 | # 5 | # set display brightness on M1 machines with Asahi 6 | # tested working on 2021 14" Macbook Pro 7 | # 8 | 9 | die() { 10 | >&2 echo "$*" 11 | exit 1 12 | } 13 | 14 | usage() { 15 | die "Usage: ${0##*/} [-i] [-d] [-s value]" 16 | } 17 | 18 | warn() { 19 | >&2 echo "$*" 20 | } 21 | 22 | isnum() { 23 | case $1 in 24 | ''|*[!0-9]*) 25 | return 1 26 | ;; 27 | *) 28 | return 0 29 | esac 30 | } 31 | 32 | clamp() { 33 | if [ "$1" -gt 255 ] ; then 34 | warn "arg \"$1\" > 255; clamping" 35 | echo 255 36 | elif [ "$1" -lt 1 ] ; then 37 | warn "arg \"$1\" < 1; clamping" 38 | echo 1 39 | else 40 | echo "$1" 41 | fi 42 | } 43 | 44 | set_br() { 45 | isnum "$1" || die "not a number" 46 | 47 | val=$(clamp "$1") 48 | 49 | path=/sys/class/backlight/apple-panel-bl/brightness 50 | 51 | if [ ! -w "$path" ] ; then 52 | printf 'No write permissions for: %s\nEnter sudo password to fix permissions.\n\n' "$path" 53 | sudo chmod 666 "$path" 54 | fi 55 | 56 | if [ -e "$path" ] ; then 57 | echo "$val" | tee "$path" 58 | else 59 | die "Error: $path doesn't seem to exist" 60 | fi 61 | } 62 | 63 | get_br() { 64 | path=/sys/class/backlight/apple-panel-bl/brightness 65 | if [ -e "$path" ] ; then 66 | cat "$path" 67 | else 68 | die "Error: $path doesn't seem to exist" 69 | fi 70 | } 71 | 72 | main() { 73 | if [ "$1" ] ; then 74 | case ${1#-} in 75 | i) set_br $(( $(get_br) + 6 )) ;; 76 | d) set_br $(( $(get_br) - 6 )) ;; 77 | s) set_br "$2" ;; 78 | *) usage 79 | esac 80 | else 81 | get_br 82 | fi 83 | } 84 | 85 | main "$@" 86 | -------------------------------------------------------------------------------- /legacy/asahi/asahi-hyprland: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # Enable GPU acceleration in Hyprland for M1 Macs on Asahi 4 | # 5 | # Note these flags reportedly have mass breakage in apps that require higher than OpenGL 3.1 6 | # So far I haven't run into any issues at least with what I use 7 | # 8 | 9 | # enable hardware acceleration in asahi 10 | # note: this is _very_ buggy and should be removed as soon as we can 11 | if uname -a | grep asahi >/dev/null ; then 12 | export MESA_GL_VERSION_OVERRIDE=3.3 13 | export MESA_GLSL_VERSION_OVERRIDE=330 14 | export MESA_GLES_VERSION_OVERRIDE=3.1 15 | fi 16 | 17 | exec Hyprland 18 | -------------------------------------------------------------------------------- /legacy/asahi/asahi-keysctl: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # https://github.com/mitchweaver/bin 4 | # 5 | # set keyboard backlight brightness on M1 machines with Asahi 6 | # tested working on 2021 14" Macbook Pro 7 | # 8 | 9 | die() { 10 | >&2 echo "$*" 11 | usage 12 | } 13 | 14 | warn() { 15 | >&2 echo "$*" 16 | } 17 | 18 | usage() { 19 | >&2 printf 'Usage: %s 1-255\n' "${0##*/}" 20 | exit 1 21 | } 22 | 23 | isnum() { 24 | case $1 in 25 | ''|*[!0-9]*) 26 | return 1 27 | ;; 28 | *) 29 | return 0 30 | esac 31 | } 32 | 33 | clamp() { 34 | if [ "$1" -gt 255 ] ; then 35 | warn "arg \"$1\" > 255; clamping" 36 | echo 255 37 | elif [ "$1" -lt 1 ] ; then 38 | warn "arg \"$1\" < 1; clamping" 39 | echo 1 40 | else 41 | echo "$1" 42 | fi 43 | } 44 | 45 | main() { 46 | isnum "$1" || die "not a number" 47 | 48 | val=$(clamp "$1") 49 | 50 | path=/sys/class/leds/kbd_backlight/brightness 51 | 52 | if [ ! -w "$path" ] ; then 53 | printf 'No write permissions for: %s\nEnter sudo password to fix permissions.\n\n' "$path" 54 | sudo chmod 666 "$path" 55 | fi 56 | 57 | if [ -e "$path" ] ; then 58 | echo "$val" | tee "$path" 59 | else 60 | die "Error: $path doesn't seem to exist" 61 | fi 62 | } 63 | 64 | main "$@" 65 | -------------------------------------------------------------------------------- /legacy/asahi/asahi-kitty: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # Launch kitty under Asahi M1 GPU drivers 4 | # 5 | # This is a hack around bypassing the OpenGL 3.3 requirement as per Martin 6 | # kitty isn't actually using any of the features past 3.1+ so its silly for 7 | # them to mandate it. 8 | # 9 | # Warning however, you ARE disabling 3.3+ for anything started from within kitty 10 | # That's why we're using this wrapper script and _NOT_ putting it in say your ~/.profile 11 | # 12 | # see suggestoin from Hector Martin here: 13 | # https://old.reddit.com/r/AsahiLinux/comments/zqejue/kitty_not_working_with_mesaasahiedge/j0y1vp3 14 | # 15 | 16 | # make sure we actually are on asahi 17 | uname -a | grep asahi >/dev/null || exec kitty "$@" 18 | 19 | # TWO SOLUTIONS: 20 | 21 | # 1. Override GL Version checks 22 | # Kitty only really uses 3.1 so the 3.3 mandate is unncessary 23 | export MESA_GL_VERSION_OVERRIDE=3.3 MESA_GLSL_VERSION_OVERRIDE=330 24 | 25 | # 2. Force software rendering 26 | # (not recommended, but if bugs with #1 --^ this will work...) 27 | ####export LIBGL_ALWAYS_SOFTWARE=true 28 | 29 | # nohup kitty >/dev/null 2>&1 & 30 | exec kitty -o linux_display_server=wayland "$@" 31 | -------------------------------------------------------------------------------- /legacy/dict: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # http://github.com/mitchweaver/bin 4 | # 5 | # quick offline dictionary 6 | # 7 | 8 | dict=${XDG_CACHE_HOME:-~/.cache}/dict.txt 9 | 10 | if [ ! -f "$dict" ] ; then 11 | url='https://raw.githubusercontent.com/sujithps/Dictionary/master/Oxford%20English%20Dictionary.txt' 12 | if ! curl -LC - "$url" -o "$dict" ; then 13 | rm "$dict" 14 | exit 1 15 | fi 16 | fi 17 | 18 | if [ "$1" ] ; then 19 | count=0 20 | grep -Ei "^$*" "$dict" | \ 21 | while read -r line ; do 22 | count=$(( count + 1 )) 23 | printf '%s\n\n' "$count. $line" 24 | done 25 | fi 26 | -------------------------------------------------------------------------------- /legacy/dl: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # http://github.com/mitchweaver 4 | # 5 | # Download All The Things! 6 | # 7 | # * assumes have "urls" script from my bin also in $PATH 8 | # 9 | # Supports: 10 | # - download multiple arguments at once 11 | # - file renaming on duplicates without clobbering 12 | # - virus scanning with clamav 13 | # - exif data stripping for images 14 | # -*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-* 15 | 16 | usage() { 17 | >&2 printf 'Usage: %s [-s scan] link(s) [-o file]\n' "${0##*/}" 18 | exit 1 19 | } 20 | 21 | die() { 22 | >&2 printf '%s\n' "$*" 23 | exit 1 24 | } 25 | 26 | check() { 27 | echo 28 | if [ "$clamscan" ]; then 29 | if command -v clamscan >/dev/null ; then 30 | printf '[*] Scanning: %s\n' "$1" 31 | clamscan --suppress-ok --no-summary --bell "$1" || \ 32 | die "Bailing out due to clamscan: $1" 33 | fi 34 | fi 35 | 36 | case ${1##*.} in 37 | jpg|jpeg|JPG|JPEG|png|PNG|tiff|TIFF|gif|GIF) 38 | printf '[*] Stripping: %s\n' "$1" 39 | 40 | exiftool -overwrite_original -all= "$1" || \ 41 | die "failed to strip: $1" 42 | 43 | case ${1##*.} in 44 | jpg|jpeg|JPG|JPEG) 45 | jpegoptim -s "$1" || die "failed to optimize: $1" 46 | esac 47 | esac 48 | } 49 | 50 | get() { 51 | if [ -z "$2" ] ; then 52 | output="$PWD/${1##*/}" 53 | else 54 | output="$2" 55 | fi 56 | 57 | if [ -e "$output" ] ; then 58 | count=$(printf '%s\n' "$output*" | grep -c "$output") 59 | output="$output($((count + 1)))" 60 | fi 61 | 62 | if wget --no-verbose --no-clobber --show-progress \ 63 | --progress=dot --continue -O "$output" "$1" ; then 64 | check "$output" || die "EXITING." 65 | fi 66 | } 67 | 68 | main() { 69 | if [ "$2" ] ; then 70 | output="$2" 71 | fi 72 | while [ "$1" ] ; do 73 | case $1 in 74 | -o) 75 | [ "$2" ] || die "no output filename" 76 | output="$2" 77 | shift 2 78 | ;; 79 | -s) 80 | clamscan=true 81 | shift 82 | ;; 83 | *) 84 | if ! command -v urls >/dev/null ; then 85 | die "Error: \"urls\" script not in \$PATH" 86 | fi 87 | if printf '%s\n' "$1" | urls >/dev/null ; then 88 | get "$1" "$output" || exit 1 89 | else 90 | >&2 printf "Error: '%s'\nIs not a URL.\nSkipping.\n" "$1" 91 | fi 92 | unset output 93 | shift 94 | break 95 | esac 96 | done 97 | } 98 | 99 | main "$@" 100 | -------------------------------------------------------------------------------- /legacy/dmoji: -------------------------------------------------------------------------------- 1 | #!/bin/sh -e 2 | # 3 | # http://github.com/mitchweaver 4 | # 5 | # select irc emoji with dmenu 6 | # 7 | 8 | : "${DMOJI_FILE:=${XDG_DOCUMENTS_DIR:-${HOME}/Documents}/dmoji.txt}" 9 | : "${MENU_PROG:=dmenu}" 10 | 11 | copy_clip() { 12 | for c in p s b ; do 13 | printf '%s' "$1" | xsel -i$c 14 | done 15 | printf '%s\n' "$1" 16 | } 17 | 18 | emoji=$($MENU_PROG -p Emoji: < "$DMOJI_FILE") 19 | [ "$emoji" ] || exit 1 20 | copy_clip "${emoji%% *}" 21 | -------------------------------------------------------------------------------- /legacy/ghmd2html: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # http://github.com/mitchweaver/bin 4 | # 5 | # easily convert md to html with github css styling 6 | # 7 | # -*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-* 8 | 9 | cssfile=${XDG_CACHE_HOME:-~/.cache}/github_md.css 10 | 11 | usage() { 12 | >&2 printf 'Usage: %s file.md\n' "${0##*/}" 13 | exit 1 14 | } 15 | 16 | if [ ! -f "$1" ] || [ ! "${1##*.}" = "md" ] ; then 17 | usage 18 | fi 19 | 20 | if [ ! -f "$cssfile" ] ; then 21 | curl -sL -o "$cssfile" \ 22 | https://github.com/sindresorhus/github-markdown-css/raw/main/github-markdown.css 23 | fi 24 | 25 | LC_ALL=en.US-UTF8 \ 26 | cat < 28 | 29 | 30 | 31 | 32 | 33 | 49 | 50 |
51 | 52 | $(curl -sL https://api.github.com/markdown/raw \ 53 | -X POST \ 54 | -H 'Content-Type: text/plain' \ 55 | -d "$(cat "$1")") 56 | 57 |
58 | 59 | EOF 60 | -------------------------------------------------------------------------------- /legacy/keys: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # http://github.com/mitchweaver/bin 4 | # 5 | # Toggles between 'us' and 'us-international' keyboard layouts. 6 | # 7 | 8 | set -- $(setxkbmap -query | grep variant) 9 | 10 | case $2 in 11 | intl) 12 | ;; 13 | *) 14 | opts='-variant intl' 15 | out=' International' 16 | esac 17 | 18 | setxkbmap -layout us $opts 19 | xmodmap ~/.xmodmaprc 20 | notify-send -t 1000 -u low "Keyboard Layout: US${out}" 21 | -------------------------------------------------------------------------------- /legacy/linux/README.md: -------------------------------------------------------------------------------- 1 | # linux 2 | 3 | Linux specific / X11 specific / Wayland specific 4 | 5 | With how good WSL2 and MacOS has become I don't use Linux as main desktop OS anymore so these have grown stale 6 | -------------------------------------------------------------------------------- /legacy/linux/backup-gnome.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh -e 2 | 3 | dir="gnome-backup-$(date +'%Y%m%d_%H%M%S')" 4 | mkdir -p "$dir/config" "$dir/local/share" 5 | 6 | dconf dump / > "$dir/dconf_dump.dconf" 7 | 8 | cp -r ~/.config/gnome-control-center "$dir/config"/ 9 | cp -r ~/.config/gnome-session "$dir/config"/ 10 | cp -r ~/.config/dconf "$dir/config"/ 11 | cp -r ~/.config/nautilus "$dir/config"/ 12 | 13 | cp -r ~/.local/gnome-shell "$dir/local"/ 14 | cp -r ~/.local/gnome-settings-daemon "$dir/local"/ 15 | cp -r ~/.local/nautilus "$dir/local"/ 16 | cp -r ~/.local/share/gnome-settings-daemon "$dir/local/share"/ 17 | cp -r ~/.local/share/gnome-shell "$dir/local/share"/ 18 | 19 | tar -cvpJf "$dir".tar.xz "$dir" && rm -r "$dir" 20 | 21 | # -------------------------------- 22 | # note to restore dconf: 23 | # $ dconf load / < dconf_dump.dconf 24 | -------------------------------------------------------------------------------- /legacy/linux/battery: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # https://github.com/mitchweaver/bin 4 | # 5 | # get battery capacity and/or discharge status 6 | # 7 | 8 | if [ -e /sys/class/power_supply/BAT ] ; then 9 | path=/sys/class/power_supply/BAT 10 | # for Macbook M1 (Asahi) 11 | elif [ -e /sys/class/power_supply/macsmc-battery ] ; then 12 | path=/sys/class/power_supply/macsmc-battery 13 | fi 14 | 15 | for i in 0 1 2 ; do 16 | if [ -e "$path$i" ] ; then 17 | path="$path$i" 18 | break 19 | fi 20 | done 21 | 22 | usage() { 23 | >&2 printf '%s\n' "Usage: ${0##*/} [-s]" 24 | exit 1 25 | } 26 | 27 | if [ "$1" ] ; then 28 | case ${1#-} in 29 | s) 30 | read -r val < "$path"/status 31 | printf '%s\n' "$val" 32 | # returns true if we are connected to power 33 | # returns false if we are discharging from battery 34 | case $val in 35 | Charging) 36 | exit 0 37 | ;; 38 | Discharging) 39 | exit 1 40 | ;; 41 | esac 42 | ;; 43 | *) 44 | usage 45 | esac 46 | else 47 | read -r val < "$path"/capacity 48 | printf '%s%%\n' "$val" 49 | fi 50 | -------------------------------------------------------------------------------- /legacy/linux/bright: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # http://github.com/mitchweaver/bin 4 | # 5 | # xbacklight brightness wrapper 6 | # 7 | 8 | usage() { 9 | >&2 printf '%s\n' "Usage: ${0##*/} [-i] [-d] [-s value]" 10 | exit 1 11 | } 12 | 13 | set_br() { 14 | xbacklight -set "$(clamp "$1")" 15 | } 16 | 17 | isnumber() { 18 | for i ; do 19 | case $i in 20 | ''|*[!0-9]*) 21 | return 1 22 | esac 23 | done 24 | } 25 | 26 | clamp() { 27 | isnumber "$1" || usage 28 | 29 | case $1 in 30 | 100*) 31 | echo 100 32 | ;; 33 | 0|-*) 34 | echo 1 35 | ;; 36 | *) 37 | printf '%s\n' "$1" 38 | esac 39 | } 40 | 41 | get() { 42 | br=$(xbacklight -get) 43 | printf '%s\n' "${br%.*}" 44 | } 45 | 46 | main() { 47 | case ${1#-} in 48 | h) 49 | usage 50 | ;; 51 | i) 52 | set_br $(( $(get) + ${2:-${BRIGHT_INCREMENT:-5}} )) 53 | ;; 54 | d) 55 | set_br $(( $(get) - ${2:-${BRIGHT_INCREMENT:-5}} )) 56 | ;; 57 | s) 58 | if [ "$2" ] ; then 59 | set_br "$2" 60 | else 61 | usage 62 | fi 63 | ;; 64 | *) 65 | printf '%s%%\n' "$(get)" 66 | esac 67 | } 68 | 69 | main "$@" 70 | -------------------------------------------------------------------------------- /legacy/linux/maild: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # http://github.com/mitchweaver 4 | # 5 | # sync my mail with isync/mbsync 6 | # note: this is for only one mailbox 7 | # 8 | 9 | # settings 10 | : "${MAILD_ACCOUNT:=?}" 11 | : "${MAILD_MAILBOX:=Inbox}" 12 | : "${MAILD_CHECK_INTERVAL:=30}" 13 | 14 | usage() { 15 | >&2 printf '%s\n' "Usage: ${0##*/} [-d]" 16 | exit 1 17 | } 18 | 19 | # test if we can reach mail server 20 | isconnected() { 21 | host=$(grep Host ~/.mbsyncrc) 22 | if ! ping -c 1 -s 1 "${host#'Host '}" >/dev/null ; then 23 | return 1 24 | fi 25 | } 26 | 27 | start_daemon() { 28 | log=${MAILD_LOGFILE:-${HOME}/.cache/${0##*/}.log} 29 | :>"$log" 30 | while : ; do 31 | if isconnected ; then 32 | mbsync -V -a "$MAILD_ACCOUNT" -m "$MAILD_MAILBOX" 33 | fi 34 | sleep "$MAILD_CHECK_INTERVAL" 35 | done >>"$log" 2>&1 36 | } 37 | 38 | main() { 39 | case ${1#-} in 40 | h) 41 | usage 42 | ;; 43 | d) 44 | start_daemon 45 | esac 46 | } 47 | 48 | main "$@" 49 | -------------------------------------------------------------------------------- /legacy/linux/menu: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # http://github.com/mitchweaver/bin 4 | # 5 | # dmenu launcher, with my patches 6 | # 7 | # see: http://github.com/mitchweaver/suckless 8 | # 9 | # shellcheck disable=2086 10 | # 11 | 12 | pgrep dmenu >/dev/null && exit 1 13 | 14 | dim=${DIMENSIONS:-$(dimensions)} 15 | 16 | # allow a wide option for longer inputs, (like urls) 17 | case $1 in 18 | -wide|--wide) 19 | w=$(( ${dim% *} - ${dim% *} / 4 )) 20 | shift 21 | ;; 22 | *) 23 | w=$(( ${dim% *} / 2 - ${dim% *} / 16)) 24 | esac 25 | 26 | fontsize=20 27 | lines=16 28 | x=$(( ${dim% *} / 2 - w / 2 )) 29 | y=$(( ${dim#* } / 2 - (lines * fontsize))) 30 | 31 | if [ "$1" = "run" ] ; then 32 | shift 33 | _run=_run 34 | fi 35 | 36 | if [ "$1" != '-w' ] ; then 37 | # only use geometry (center into screen) 38 | # if we weren't given a window id to embed into 39 | geom="-x $x -y $y -wi $w" 40 | fi 41 | 42 | exec dmenu${_run} -i -f -l "$lines" $geom "$@" 43 | -------------------------------------------------------------------------------- /legacy/linux/rbag: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # http://github.com/mitchweaver 4 | # 5 | # easily get/set dpi for logitech mice on linux 6 | # 7 | 8 | die() { 9 | >&2 printf '%s\n' "$*" 10 | exit 1 11 | } 12 | 13 | usage() { 14 | die "Usage: ${0##*/} [-g] [-s dpi]" 15 | } 16 | 17 | get_device() { 18 | ratbagctl list >/dev/null || die 'No devices found.' 19 | name=$(ratbagctl list) 20 | printf '%s\n' "${name%%:*}" 21 | } 22 | 23 | main() { 24 | if ! pgrep -f ratbagd >/dev/null ; then 25 | >&2 echo "ratbagd isn't running. enter password to start it:" 26 | if command -v systemctl > /dev/null ; then 27 | sudo systemctl enable ratbagd 28 | sudo systemctl start ratbagd 29 | sudo systemctl daemon-reload 30 | sudo systemctl reload dbus.service 31 | sudo systemctl restart ratbagd 32 | else 33 | sudo rc-service ratbagd stop 34 | sudo rc-service ratbagd start 35 | fi 36 | fi 37 | 38 | case ${1#-} in 39 | h) 40 | usage 41 | ;; 42 | [0-9]*) 43 | ratbagctl "$(get_device)" dpi set "$1" 44 | ;; 45 | s) 46 | ratbagctl "$(get_device)" dpi set "${2:-?}" 47 | ;; 48 | g) 49 | ratbagctl "$(get_device)" dpi get 50 | ;; 51 | *) 52 | exit 1 53 | esac 54 | printf 'new dpi: %s' "$(ratbagctl "$(get_device)" dpi get)" 55 | xset m 0 0 56 | } 57 | 58 | main "$@" 59 | -------------------------------------------------------------------------------- /legacy/linux/temp: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # https://github.com/mitchweaver 4 | # 5 | # get average CPU temperature on Linux with lm-sensors 6 | # 7 | # shellcheck disable=SC2086,SC2126 8 | # 9 | 10 | printf '%s°C\n' \ 11 | "$( 12 | 13 | bc << EOF 14 | scale=1; 15 | $( 16 | sensors | \ 17 | while read -r line ; do 18 | case $line in 19 | *Core*) 20 | set -- $line 21 | temp=$3 22 | temp=${temp##+} 23 | temp=${temp%%°C} 24 | printf '%s\n' "$temp" 25 | esac 26 | done | paste -sd+ | bc) / $(sensors | grep Core | wc -l) 27 | EOF 28 | 29 | )" 30 | -------------------------------------------------------------------------------- /legacy/linux/x9term: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # http://github.com/mitchweaver/bin 4 | # 5 | # plan9 rio style terminal drawing in X 6 | # 7 | # you can get my fork of xrectsel here: 8 | # http://github.com/mitchweaver/xrectsel 9 | # 10 | 11 | if command -v xrectsel >/dev/null ; then 12 | pgrep xrectsel >/dev/null && exit 1 13 | geom=$(xrectsel -f '%wx%h+%x+%y') 14 | elif command -v slop >/dev/null ; then 15 | pgrep slop >/dev/null && exit 1 16 | geom=$(slop -f '%wx%h+%x+%y') 17 | fi 18 | 19 | [ "$geom" ] || exit 1 20 | 21 | exec tabbed -c -k -n "${0##*/}" -g "$geom" -r 2 \ 22 | st -w '' -c "${0##*/}" -T "${0##*/}" -e "${*:-$SHELL}" 23 | -------------------------------------------------------------------------------- /legacy/lock: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # http://github.com/mitchweaver/bin 4 | # 5 | # lockscreen wrapper around interchangeable between x11/wayland 6 | # 7 | # 1. i3lock-fancy-rapid (x11) 8 | # 9 | # see: https://github.com/yvbbrjdr/i3lock-fancy-rapid 10 | # 11 | # 2. swaylock (wayland) 12 | # 13 | # 14 | 15 | case $(wayland_or_x11) in 16 | x11|X11) 17 | i3lock-fancy-rapid 10 pixel -e 18 | ;; 19 | wayland) 20 | file=/tmp/${USER}-lock-$$.png 21 | # attempt to make a blurred lockscreen background 22 | # if this fails for whatever reason continue to lock the screen with solid black instead 23 | if grim -l 2 "$file" && convert -filter Gaussian -resize 20% -blur 0x2.5 -resize 500% "$file" "$file" ; then 24 | swaylock -e -f -i "$file" 25 | rm -- "$file" 2>/dev/null ||: 26 | else 27 | swaylock -e -f -c 000000 28 | fi 29 | ;; 30 | *) 31 | >&2 echo "could not determine graphical session" 32 | exit 1 33 | esac 34 | -------------------------------------------------------------------------------- /legacy/mag: -------------------------------------------------------------------------------- 1 | #!/bin/sh -e 2 | # 3 | # http://github.com/mitchweaver 4 | # 5 | # wrapper around my commonly used imagemagick commands 6 | # 7 | # - - - - - - - - - - - - - - - - - - - - - - - - - - - 8 | 9 | # Source colors from current running theme. 10 | if [ -f ~/src/dots/themes/current ] ; then 11 | # shellcheck disable=SC1090 12 | . ~/src/dots/themes/current 13 | else 14 | # If not found, it is the usual 15 | # off-white yellowish background I use 16 | background='#d9d5ba' 17 | fi 18 | 19 | # default file name if no $3 is given 20 | DEFAULT=out.png 21 | 22 | usage() { 23 | >&2 cat </dev/null ||: 62 | # resizes an image to a given percent 63 | mogrify -resize "${1#-}%x${1#-}%" "${3:-$DEFAULT}" 64 | ;; 65 | 1080) 66 | # make copy as mogrify has no way of outputting 67 | # to a different file 68 | cp -f "$2" "${3:-$DEFAULT}" 2>/dev/null ||: 69 | # resize image to 1920x1080 70 | mogrify -resize '1920x1080' "${3:-$DEFAULT}" 71 | ;; 72 | *) 73 | usage 74 | esac 75 | -------------------------------------------------------------------------------- /legacy/md2html: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # http://github.com/mitchweaver/bin 4 | # 5 | # convert md to html with github css styling 6 | # 7 | 8 | cssfile=${XDG_CACHE_HOME:-~/.cache}/github_md.css 9 | 10 | usage() { 11 | >&2 printf 'Usage: %s file.md\n' "${0##*/}" 12 | exit 1 13 | } 14 | 15 | if [ ! -f "$1" ] || [ ! "${1##*.}" = "md" ] ; then 16 | usage 17 | fi 18 | 19 | if [ ! -f "$cssfile" ] ; then 20 | curl -sL -o "$cssfile" \ 21 | https://github.com/sindresorhus/github-markdown-css/raw/main/github-markdown.css 22 | fi 23 | 24 | LC_ALL=en.US-UTF8 \ 25 | cat < 27 | 28 | 29 | 30 | 31 | 32 | 48 | 49 |
50 | 51 | $(curl -sL https://api.github.com/markdown/raw \ 52 | -X POST \ 53 | -H 'Content-Type: text/plain' \ 54 | -d "$(cat "$1")") 55 | 56 |
57 | 58 | EOF 59 | -------------------------------------------------------------------------------- /legacy/mmt: -------------------------------------------------------------------------------- 1 | #!/bin/sh -e 2 | # 3 | # http://github.com/mitchweaver/bin 4 | # 5 | # ▙▗▌▗▐ ▌ ▝▌ ▙▗▌▛▀▖▌ ▌ ▀▛▘ ▜ 6 | # ▌▘▌▄▜▀ ▞▀▖▛▀▖▝▞▀▘ ▌▘▌▙▄▘▚▗▘ ▌▞▀▖▞▀▖▐ 7 | # ▌ ▌▐▐ ▖▌ ▖▌ ▌ ▝▀▖ ▌ ▌▌ ▝▞ ▌▌ ▌▌ ▌▐ 8 | # ▘ ▘▀▘▀ ▝▀ ▘ ▘ ▀▀ ▘ ▘▘ ▘ ▘▝▀ ▝▀ ▘ 9 | # 10 | # control mpv through a socket with nc 11 | # 12 | 13 | sock=${MPV_SOCKET:-/tmp/mpvsocket} 14 | 15 | usage() { 16 | >&2 cat <&2 printf '%s\n' "$*" 39 | exit 1 40 | } 41 | 42 | isrunning() { 43 | # old: a way to check the socket 44 | # using openbsd-netcat 45 | # ! : | nc -U -- "$sock" 2>/dev/null 46 | 47 | # check is socket exists 48 | if [ ! -S "$sock" ] ; then 49 | die "$sock does not exist." 50 | # check if socket is being listened on 51 | elif ! ss -l | grep /tmp/mpvsocket >/dev/null ; then 52 | die "mpv is not playing on $sock" 53 | fi 54 | } 55 | 56 | cmd() { 57 | isrunning 58 | printf '%s\n' "$*" | nc -U -- "$sock" 59 | } 60 | 61 | get() { 62 | res=$(cmd "{\"command\": [\"get_property_string\", \"$1\"]}\"") 63 | res=${res%,\"re*} 64 | res=${res%\"} 65 | res=${res#*\":} 66 | res=${res#\"} 67 | printf '%s\n' "$res" 68 | } 69 | 70 | case $1 in 71 | *t) 72 | cmd cycle pause 73 | ;; 74 | *n) 75 | cmd playlist-next 76 | ;; 77 | *p) 78 | cmd playlist-prev 79 | ;; 80 | *f) 81 | cmd seek +30 82 | ;; 83 | *b) 84 | cmd seek -30 85 | ;; 86 | *q) 87 | cmd quit 88 | ;; 89 | *i) 90 | isrunning >/dev/null 2>&1 91 | exit $? 92 | ;; 93 | *k) 94 | case $2 in 95 | filename) 96 | get filename 97 | ;; 98 | artist) 99 | get 'metadata/by-key/artist' 100 | ;; 101 | album) 102 | get 'metadata/by-key/album' 103 | ;; 104 | year) 105 | get 'metadata/by-key/date' 106 | ;; 107 | title) 108 | title=$(get 'metadata/by-key/title') 109 | if [ "$title" = null ] ; then 110 | title=$(get 'metadata/by-key/icy-title') 111 | fi 112 | printf '%s\n' "$title" 113 | ;; 114 | *) 115 | usage 116 | esac 117 | ;; 118 | *) 119 | usage 120 | esac 121 | -------------------------------------------------------------------------------- /legacy/note: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # http://github.com/mitchweaver/bin 4 | # 5 | # n - simple notes 6 | # 7 | 8 | usage() { 9 | >&2 printf '%s\n' "Usage: ${0##*/} [-f] [-c] [-d] [-v]" 10 | exit 1 11 | } 12 | 13 | if [ "$1" = '-f' ] ; then 14 | [ "$2" ] || usage 15 | f=$2 16 | [ -f "$2" ] || :>"$f" 17 | shift 2 18 | else 19 | f=${XDG_DOCUMENTS_DIR:-~/files}/notes.txt 20 | fi 21 | 22 | case $1 in 23 | ''|-h) usage ;; 24 | -c) tail -n 20 "$f" ;; 25 | -d) sed -i '$d' "$f" ;; 26 | -v) $EDITOR "$f" ;; 27 | *) printf '%s\n' "$(date +%m-%d): $*" >>"$f" 28 | esac 29 | -------------------------------------------------------------------------------- /legacy/openbsd/README.md: -------------------------------------------------------------------------------- 1 | # OpenBSD 2 | 3 | Scripts with relevance only with OpenBSD 4 | -------------------------------------------------------------------------------- /legacy/openbsd/allowrecord: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # http://github.com/mitchweaver 4 | # 5 | # enable webcam/microphone in kernel on OpenBSD 6 | # 7 | 8 | usage() { 9 | >&2 printf 'Usage: %s [-y yes] [-n no]\n' "${0##*/}" 10 | exit 1 11 | } 12 | 13 | 14 | case ${1#-} in 15 | h) 16 | usage 17 | ;; 18 | y) 19 | doas sysctl kern.audio.record=1 20 | doas sysctl kern.video.record=1 21 | doas chmod 777 /dev/video* 22 | doas chmod 777 /dev/audio* 23 | ;; 24 | n) 25 | doas sysctl kern.audio.record=0 26 | doas sysctl kern.video.record=0 27 | doas chmod 600 /dev/video* 28 | doas chmod 600 /dev/audio* 29 | ;; 30 | *) 31 | sysctl kern.audio.record 32 | sysctl kern.video.record 33 | esac 34 | -------------------------------------------------------------------------------- /legacy/openbsd/grab_ports.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh -e 2 | # 3 | # http://github.com/mitchweaver/bin 4 | # 5 | # shellcheck disable=2046 6 | # 7 | 8 | case $(uname) in 9 | OpenBSD) 10 | ;; 11 | *) 12 | exit 1 13 | esac 14 | 15 | if [ ! -d /usr/ports ] ; then 16 | cd /tmp 17 | for f in ports.tar.gz SHA256.sig ; do 18 | ftp https://cdn.openbsd.org/pub/OpenBSD/$(uname -r)/$f 19 | done 20 | signify -Cp \ 21 | -x /etc/signify/openbsd-$(uname -r | cut -c 1,3)-base.pub \ 22 | ports.tar.gz 23 | mkdir -p /usr/ports 24 | cd /usr 25 | tar xvzf /tmp/ports.tar.gz 26 | rm /tmp/ports.tar.gz /tmp/SHA256.sig 27 | 28 | git clone https://github.com/jasperla/openbsd-wip /usr/ports/openbsd-wip 29 | fi 30 | -------------------------------------------------------------------------------- /legacy/openbsd/interface: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # http://github.com/mitchweaver 4 | # 5 | # network interface helper for OpenBSD 6 | # 7 | 8 | usage() { 9 | printf '%s\n' "${0##*/}: [-l list] [-u list up]" 10 | } 11 | 12 | list() { 13 | ifconfig | while read -r line ; do 14 | case $line in 15 | # junk 16 | ' '*|groups*|media*|status*|ieee*) 17 | ;; 18 | # virtual interfaces 19 | lo*|pflog*|enc*) 20 | ;; 21 | *': '*) 22 | printf '%s\n' "${line%%:*}" 23 | esac 24 | done 25 | } 26 | 27 | # lists interfaces that are up 28 | listup() { 29 | list | while read -r int ; do 30 | ifconfig "$int" | while read -r line ; do 31 | case $line in 32 | *'status: active'*) 33 | printf '%s\n' "$int" 34 | ;; 35 | esac 36 | done 37 | done 38 | } 39 | 40 | main() { 41 | case $1 in 42 | -h) 43 | usage 44 | ;; 45 | -u) 46 | listup 47 | ;; 48 | *) 49 | list 50 | 51 | esac 52 | } 53 | 54 | main "$@" 55 | -------------------------------------------------------------------------------- /legacy/openbsd/pledgetrace: -------------------------------------------------------------------------------- 1 | #!/bin/sh -e 2 | # 3 | # http://github.com/mitchweaver/bin 4 | # 5 | # Helper for determing what syscalls a program uses 6 | # to more easily implement pledge(2) on OpenBSD. 7 | # 8 | # Ties closely with ktrace(1), kdump(1) 9 | # 10 | # Important: Not all pledges are syscalls, many instead are 11 | # based on operations on certain filepaths or devices. 12 | # See notes below for the exceptions. 13 | # 14 | # shellcheck disable=2034,2221,2222 15 | # 16 | # -*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-* 17 | # 18 | # note: ps, vminfo relate to sysctl(2) calls 19 | # 20 | # note: prot_exec relates to PROT_EXEC mmap(2), mprotect(2) 21 | # 22 | # note: tape, tape drive operations 23 | # 24 | # note: tty: ioctl(2) on /dev/tty 25 | # 26 | # TIOCSPGRP, TIOCGETA, TIOCGPGRP, TIOCGWINSZ, TIOCSWINSZ, 27 | # TIOCSBRK, TIOCCDTR, TIOCSETA, TIOCSETAW, TIOCSETAF, 28 | # TIOCUCNTL 29 | # 30 | # note: pf relates to ioctl(2) calls on the pf(4) device: 31 | # 32 | # DIOCADDRULE, DIOCGETSTATUS, DIOCNATLOOK, 33 | # DIOCRADDTABLES, DIOCRCLRADDRS, DIOCRCLRTABLES, 34 | # DIOCRCLRTSTATS, DIOCRGETTSTATS, DIOCRSETADDRS, 35 | # DIOCXBEGIN, DIOCXCOMMIT 36 | # 37 | # note: route - allow inspection to routing table 38 | # wroute - allow changes to routing table 39 | # 40 | # note: audio ioctl(2) calls: 41 | # 42 | # AUDIO_GETPOS, AUDIO_GETPAR, AUDIO_SETPAR, AUDIO_START, 43 | # AUDIO_STOP, AUDIO_MIXER_DEVINFO, AUDIO_MIXER_READ, 44 | # AUDIO_MIXER_WRITE 45 | # 46 | # note: video ioctl(2) calls: 47 | # 48 | # VIDIOC_DQBUF, VIDIOC_ENUM_FMT, 49 | # VIDIOC_ENUM_FRAMEINTERVALS, VIDIOC_ENUM_FRAMESIZES, 50 | # VIDIOC_G_CTRL, VIDIOC_G_PARM, VIDIOC_QBUF, 51 | # VIDIOC_QUERYBUF, VIDIOC_QUERYCAP, VIDIOC_QUERYCTRL, 52 | # VIDIOC_S_CTRL, VIDIOC_S_FMT, VIDIOC_S_PARM, 53 | # VIDIOC_STREAMOFF, VIDIOC_STREAMON, VIDIOC_TRY_FMT, 54 | # VIDIOC_REQBUFS 55 | # 56 | # note: bpf 57 | # 58 | # Allow BIOCGSTATS operation for statistics 59 | # collection from a bpf(4) device. 60 | # 61 | # note: error 62 | # 63 | # Rather than killing the process upon violation, 64 | # indicate error with ENOSYS. 65 | # 66 | 67 | print_keywords() { 68 | case $1 in 69 | clock_getres|clock_gettime|close|closefrom|dup|dup2|dup3|\ 70 | fchdir|fcntl|fstat|fsync|ftruncate|getdents|getdtablecount|\ 71 | getegid|getentropy|geteuid|getgid|getgroups|getitimer|\ 72 | getlogin|getpgid|getpgrp|getpid|getppid|getresgid|getresuid|\ 73 | getrlimit|getrtable|getsid|getthrid|gettimeofday|getuid|\ 74 | issetugid|kevent|kqueue|lseek|madvise|minherit|mmap|mprotect|\ 75 | mquery|munmap|nanosleep|pipe|pipe2|poll|pread|preadv|pwrite|\ 76 | pwritev|read|readv|recvfrom|recvmsg|select|sendmsg|sendsyslog|\ 77 | sendto|setitimer|shutdown|sigaction|sigprocmask|sigreturn|\ 78 | socketpair|umask|wait4|write|writev) 79 | printf '%s\n' stdio 80 | ;; 81 | chdir|getcwd|openat|fstatat|faccessat|readlinkat|lstat|chmod|\ 82 | fchmod|fchmodat|chflags|chflagsat|chown|fchown|fchownat|fstat|\ 83 | getfsstat) 84 | printf '%s\n' rpath 85 | ;; 86 | getcwd|openat|fstatat|faccessat|readlinkat|lstat|chmod|\ 87 | fchmod|fchmodat|chflags|chflagsat|chown|fchown|fchownat|fstat) 88 | printf '%s\n' wpath 89 | ;; 90 | rename|renameat|link|linkat|symlink|symlinkat|unlink|\ 91 | unlinkat|mkdir|mkdirat|rmdir) 92 | printf '%s\n' cpath 93 | ;; 94 | mkfifo|mknod) 95 | printf '%s\n' dpath 96 | ;; 97 | lstat|chmod|chflags|chown|unlink|fstat) 98 | printf '%s\n' tmppath 99 | ;; 100 | socket|listen|bind|connect|accept4|accept|\ 101 | getpeername|getsockname|setsockopt|getsockopt) 102 | printf '%s\n' inet 103 | ;; 104 | setsockopt) 105 | printf '%s\n' mcast 106 | ;; 107 | futimes|utimensat|futimens|chmod|fchmod|fchmodat|\ 108 | chflags|chflagsat|chown|fchownat|lchown|fchown|utimes) 109 | printf '%s\n' fattr 110 | ;; 111 | chown) 112 | printf '%s\n' chown 113 | ;; 114 | fcntl|flock|lockf|open) 115 | printf '%s\n' flock 116 | ;; 117 | socket|listen|bind|connect|accept4|accept|getpeername|\ 118 | getsockname|setsockopt|getsockopt) 119 | printf '%s\n' unix 120 | ;; 121 | sendto|recvfrom|socket|connect) 122 | printf '%s\n' dns 123 | ;; 124 | getpwnam|getgrnam|getgrouplist|initgroups) 125 | printf '%s\n' getpw 126 | ;; 127 | sendmsg) 128 | printf '%s\n' sendfd 129 | ;; 130 | recvmsg) 131 | printf '%s\n' recvfd 132 | ;; 133 | fork|vfork|kill|getpriority|setpriority|\ 134 | setrlimit|setpgid|setsid) 135 | printf '%s\n' proc 136 | ;; 137 | execve) 138 | printf '%s\n' exec 139 | ;; 140 | settimeofday|adjtime|adjfreq) 141 | printf '%s\n' settime 142 | ;; 143 | setuid|seteuid|setreuid|setresuid|setgid|setegid|\ 144 | setregid|setresgid|setgroups|setlogin|setrlimit|\ 145 | getpriority|setpriority) 146 | printf '%s\n' id 147 | ;; 148 | unveil) 149 | printf '%s\n' unveil 150 | esac 151 | } 152 | 153 | usage() { 154 | >&2 printf 'Usage: %s [program] or [ktrace.out]\n' "${0##*/}" 155 | exit 1 156 | } 157 | 158 | parse_dumpfile() { 159 | kdump -f "$1" | \ 160 | while read -r addr name op syscall code ; do 161 | syscall=${syscall%% *} 162 | syscall=${syscall%%\(*} 163 | printf '%s\n' "$syscall" 164 | done | \ 165 | sort -du | \ 166 | while read -r line ; do 167 | print_keywords "$line" 168 | done | \ 169 | sort -u 170 | } 171 | 172 | main() { 173 | case $1 in 174 | -h|--help) 175 | usage 176 | ;; 177 | *) 178 | printf 'Given program: %s\n' "$1" 179 | if [ -x "$1" ] ; then 180 | trap 'rm ktrace.out' EXIT 181 | ktrace -tc -- "$@" 182 | else 183 | usage 184 | fi 185 | esac 186 | 187 | if [ -f ktrace.out ] ; then 188 | parse_dumpfile ktrace.out 189 | else 190 | usage 191 | fi 192 | } 193 | 194 | main "$@" 195 | -------------------------------------------------------------------------------- /legacy/openbsd/seq: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # seq wrapper for OpenBSD's jot 4 | # 5 | exec jot "$@" 6 | -------------------------------------------------------------------------------- /legacy/openbsd/watch: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # http://github.com/mitchweaver/bin 4 | # 5 | # watch command for coreutils that don't have watch, (like OpenBSD) 6 | # 7 | 8 | usage() { 9 | >&2 printf '%s\n' "Usage: ${0##*/} [-n seconds] command" 10 | exit 1 11 | } 12 | 13 | while [ "$1" ] ; do 14 | case ${1#-} in 15 | h) 16 | usage 17 | ;; 18 | n) 19 | if [ "$2" ] ; then 20 | secs=$2 21 | shift 2 22 | else 23 | usage 24 | fi 25 | ;; 26 | *) 27 | cmd=$* 28 | break 29 | esac 30 | done 31 | 32 | if [ "$cmd" ] ; then 33 | while eval "$cmd" ; do 34 | sleep "${secs:-1}" 35 | done 36 | else 37 | usage 38 | fi 39 | -------------------------------------------------------------------------------- /legacy/pape: -------------------------------------------------------------------------------- 1 | #!/bin/sh -e 2 | # 3 | # http://github.com/mitchweaver/bin 4 | # 5 | # grab a pape from unsplash and set it 6 | # 7 | # with no search terms provided, it is random 8 | # 9 | 10 | dir=${XDG_CACHE_HOME:-${HOME}/.cache}/pape 11 | file=$dir/pape-$$.jpg 12 | mkdir -p "$dir" 13 | 14 | usage() { 15 | >&2 printf 'Usage: %s [-s save] \n' "${0##*/}" 16 | exit 17 | } 18 | 19 | case $1 in 20 | -s) 21 | cp -fv "$dir"/last_pape.jpg "${HOME}/$$-pape.jpg" 22 | exit 23 | ;; 24 | -h) 25 | usage 26 | ;; 27 | *) 28 | # if you have my dimensions script 29 | if command -v dimensions >/dev/null ; then 30 | # shellcheck disable=2046 31 | size=$(dimensions | sed 's/ /x/') 32 | url="https://source.unsplash.com/$size/?$(printf '%s\n' "$@" | tr ' ' ',')" 33 | fi 34 | esac 35 | 36 | : "${url:=https://source.unsplash.com/random/1920x1080}" 37 | printf 'downloading: %s\n' "$url" 38 | curl -L -# -C - -o "$file" --url "$url" 39 | 40 | ln -sf "$file" "$dir"/last_pape.jpg 41 | background "$file" 42 | -------------------------------------------------------------------------------- /legacy/paped: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # http://github.com/mitchweaver/bin 4 | # 5 | # continuously download and set wallpaper in the background 6 | # 7 | # deps: pape, background (from same repo) 8 | # 9 | 10 | usage() { 11 | >&2 printf 'Usage: %s [-m interval] [-l local_dir]\n' "${0##*/}" 12 | exit 1 13 | } 14 | 15 | main() { 16 | while [ "$1" ] ; do 17 | case ${1#-} in 18 | i) 19 | INTERVAL=${2:-5} 20 | shift 2 21 | ;; 22 | l) 23 | LOCAL_DIR="$2" 24 | shift 2 25 | ;; 26 | *) 27 | usage 28 | esac 29 | done 30 | 31 | daemon 32 | } 33 | 34 | daemon() { 35 | if [ -d "$LOCAL_DIR" ] ; then 36 | while background \ 37 | "$(find "$LOCAL_DIR" -type f \ 38 | -name '*.jpg' -o -name '*.png' | \ 39 | sort -R | head -n 1)" 40 | do 41 | sleep $(( ${INTERVAL:-5} * 60 )) 42 | done 43 | else 44 | while pape ; do 45 | sleep $(( ${INTERVAL:-5} * 60 )) 46 | done & 47 | fi 48 | } 49 | 50 | main "$@" 51 | -------------------------------------------------------------------------------- /legacy/pdf2txt: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # https://github.com/mitchweaver/bin 4 | # 5 | # convert .pdf to .txt 6 | # 7 | # can read pdf in terminal for example: 8 | # $ pdf2txt file.pdf | less 9 | # 10 | 11 | usage() { 12 | >&2 printf 'Usage: %s file.pdf\n' "${0##*/}" 13 | exit 1 14 | } 15 | 16 | if [ -f "$1" ] ; then 17 | case $1 in 18 | *.pdf|*.PDF) 19 | mutool draw -F txt -i -- "$1" 2>/dev/null | sed 's/[^[:print:]]//g' | tr -s '[:blank:]' 20 | ;; 21 | *) 22 | usage 23 | esac 24 | else 25 | usage 26 | fi 27 | -------------------------------------------------------------------------------- /legacy/quote: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # http://github.com/mitchweaver/bin 4 | # 5 | # wraps piped text in quotes 6 | # 7 | 8 | while read -r line ; do 9 | printf '"%s"\n' "$line" 10 | done 11 | -------------------------------------------------------------------------------- /legacy/record: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # http://github.com/mitchweaver/bin 4 | # 5 | # record a selected rectangle with ffmpeg 6 | # 7 | # deps: ffmpeg, xrectsel|slop 8 | # 9 | # xrectsel can be found here: http://github.com/mitchweaver/xrectsel 10 | # 11 | 12 | # -*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-* 13 | # ▞▀▖ ▐ ▐ ▗ 14 | # ▚▄ ▞▀▖▜▀ ▜▀ ▄ ▛▀▖▞▀▌▞▀▘ 15 | # ▖ ▌▛▀ ▐ ▖▐ ▖▐ ▌ ▌▚▄▌▝▀▖ 16 | # ▝▀ ▝▀▘ ▀ ▀ ▀▘▘ ▘▗▄▘▀▀ 17 | : "${RECORD_FRAMERATE:=30}" 18 | : "${RECORD_OUTPUT_DIR:=$PWD}" 19 | # -*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-* 20 | 21 | mkdir -p /tmp/record 22 | sock=/tmp/record/sock 23 | pidfile=/tmp/record/pidfile 24 | 25 | msg() { printf '* %s\n' "$*" ; } 26 | die() { >&2 msg "$*" ; exit 1 ; } 27 | 28 | usage() { 29 | die "Usage: ${0##*/} [-o output dir] [-r rate] [-f foreground]" 30 | } 31 | 32 | isrunning() { kill -0 "$(getpid)" 2>/dev/null ; return $? ; } 33 | 34 | getpid() { 35 | [ -s $pidfile ] && read -r pid <$pidfile 36 | echo "${pid:-?}" 37 | } 38 | 39 | start() { 40 | isrunning && die "Another instance already exists: $(getpid)" 41 | 42 | file="$RECORD_OUTPUT_DIR/record-$(date "+%Y.%m.%d-%H:%M:%S").mp4" 43 | :>$sock 44 | 45 | if command -v xrectsel >/dev/null ; then 46 | xrectsel -f '%x %y %w %h' 47 | elif command -v slop >/dev/null ; then 48 | slop -f '%x %y %w %h' 49 | else 50 | die 'Needs xrectsel or slop' 51 | fi | { 52 | read -r x y w h 53 | 54 | <$sock ffmpeg -y -f x11grab -s "${w}x${h}" -r $RECORD_FRAMERATE \ 55 | -i "${DISPLAY:-:0}+${x},${y}" -vcodec libx264 \ 56 | -pix_fmt yuv420p -filter:v "crop=iw-mod(iw\\,2):ih-mod(ih\\,2)" \ 57 | "$file" >/tmp/record/log 2>&1 & 58 | 59 | msg "recording on pid $!" 60 | 61 | if ${FOREGROUND:-false} ; then 62 | trap 'rm "$sock" /tmp/record/log 2>/dev/null ||: ; rmdir /tmp/record 2>/dev/null ||:' EXIT INT TERM 63 | wait 64 | else 65 | echo $! >$pidfile 66 | echo "$file" >/tmp/record/file 67 | fi 68 | } 69 | } 70 | 71 | end() { 72 | if isrunning ; then 73 | echo q >>$sock 74 | read -r name /dev/null ||: 77 | rmdir /tmp/record 2>/dev/null ||: 78 | exit 79 | else 80 | die 'Nothing being recorded.' 81 | fi 82 | } 83 | 84 | toggle() { 85 | if isrunning ; then 86 | end 87 | else 88 | start 89 | fi 90 | } 91 | 92 | while [ "$1" ] ; do 93 | case $1 in 94 | -f) 95 | FOREGROUND=true 96 | ;; 97 | -r) 98 | RECORD_FRAMERATE=$1 99 | ;; 100 | -o) 101 | [ -d "$2" ] || usage 102 | RECORD_OUTPUT_DIR=$2 103 | shift 104 | ;; 105 | *) usage 106 | esac 107 | shift 108 | done 109 | 110 | toggle 111 | -------------------------------------------------------------------------------- /legacy/rice: -------------------------------------------------------------------------------- 1 | #!/bin/sh -e 2 | # 3 | # http://github.com/mitchweaver/bin 4 | # 5 | # autoricer 6 | # 7 | # shellcheck disable=1090,2154,2086 8 | # 9 | 10 | set_background() { 11 | [ -f "$1" ] && background $BLUR "$1" 12 | } 13 | 14 | gen_st() { 15 | cat > "${XDG_CACHE_HOME:-${HOME}/.cache}"/themes/st.h << EOF 16 | const char *colorname[] = { 17 | [0] = "$color0", 18 | [1] = "$color1", 19 | [2] = "$color2", 20 | [3] = "$color3", 21 | [4] = "$color4", 22 | [5] = "$color5", 23 | [6] = "$color6", 24 | [7] = "$color7", 25 | [8] = "$color8", 26 | [9] = "$color9", 27 | [10] = "$color10", 28 | [11] = "$color11", 29 | [12] = "$color12", 30 | [13] = "$color13", 31 | [14] = "$color14", 32 | [15] = "$color15", 33 | [256] = "$background", 34 | [257] = "$foreground", 35 | [258] = "$cursor", 36 | }; 37 | unsigned int defaultbg = 256; 38 | unsigned int defaultfg = 257; 39 | unsigned int defaultcs = 258; 40 | unsigned int defaultrcs = 257; 41 | EOF 42 | } 43 | 44 | gen_dmenu() { 45 | cat > "${XDG_CACHE_HOME:-${HOME}/.cache}"/themes/dmenu.h << EOF 46 | static const char *colors[SchemeLast][2] = { 47 | [SchemeNorm] = { "$foreground", "$background" }, 48 | [SchemeSel] = { "$foreground", "$color6" }, 49 | [SchemeOut] = { "$foreground", "$color5" }, 50 | }; 51 | EOF 52 | } 53 | 54 | gen_dwm() { 55 | cat > "${XDG_CACHE_HOME:-${HOME}/.cache}"/themes/dwm.h << EOF 56 | static const char *colors[][3] = { 57 | [SchemeNorm] = { "$foreground", "$background", "$color6" }, 58 | [SchemeSel] = { "$foreground", "$color6", "$color4" }, 59 | [SchemeUrg] = { "$foreground", "$color1", "$color1" }, 60 | }; 61 | EOF 62 | } 63 | 64 | gen_tabbed() { 65 | cat > "${XDG_CACHE_HOME:-${HOME}/.cache}"/themes/tabbed.h << EOF 66 | static const char* selfgcolor = "$foreground"; 67 | static const char* selbgcolor = "$background"; 68 | static const char* normfgcolor = "$foreground"; 69 | static const char* normbgcolor = "$color2"; 70 | static const char* urgfgcolor = "$foreground"; 71 | static const char* urgbgcolor = "$color1"; 72 | EOF 73 | } 74 | 75 | gen_files() { 76 | gen_st 77 | gen_dwm 78 | gen_dmenu 79 | gen_tabbed 80 | } 81 | 82 | 83 | rebuild() { 84 | # rebuild suckless tools 85 | cd ~/src/suckless 86 | ./build.sh dwm st dmenu 87 | # ./build.sh st dwm dmenu tabbed 88 | cd - 89 | } 90 | 91 | usage() { 92 | >&2 printf '%s [-l light] [-g generate-only] wallpaper\n' "${0##*/}" 93 | exit 1 94 | } 95 | 96 | main() { 97 | while [ "$1" ] ; do 98 | case ${1#-} in 99 | h) 100 | usage 101 | ;; 102 | b) 103 | BLUR=-b 104 | ;; 105 | l) 106 | LIGHT=-l 107 | ;; 108 | c) 109 | COLORZ=true 110 | ;; 111 | *) 112 | break 113 | esac 114 | shift 115 | done 116 | 117 | if [ -f "$1" ] ; then 118 | FILE=$1 119 | else 120 | FILE=${HOME}/.local/wallpaper 121 | fi 122 | 123 | [ -f "$FILE" ] || exit 1 124 | 125 | mkdir -p "${XDG_CACHE_HOME:-${HOME}/.cache}"/themes 126 | 127 | # note: need haishoku/colorz backends, looks better than wal's 128 | # install it via pip 129 | # https://github.com/metakirby5/colorz 130 | # --saturate 0.4 131 | if command -v wal >/dev/null ; then 132 | if [ "$COLORZ" ] ; then 133 | wal -q -n -e -t -s $LIGHT --backend colorz -i "$FILE" 134 | else 135 | wal -q -n -e -t -s $LIGHT -i "$FILE" 136 | fi 137 | ln -sf ~/.cache/wal/colors.sh ~/src/dots/themes/current 138 | fi 139 | 140 | # set background if given 141 | set_background "$FILE" 142 | 143 | if [ -e ~/.Xresources ] ; then 144 | xrdb load ~/.Xresources 145 | fi 146 | 147 | # load current theme into environment 148 | . ~/.cache/themes/current 149 | 150 | # generate .h theme files for suckless tools 151 | gen_files 152 | 153 | # link kitty pywal theme 154 | sh ~/.config/kitty/pywal.sh 155 | 156 | # regen mako theme 157 | sh ~/.config/mako/update-theme.sh 158 | } 159 | 160 | main "$@" 161 | -------------------------------------------------------------------------------- /legacy/rotate: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # http://github.com/mitchweaver/bin 4 | # 5 | # screen rotator 6 | # 7 | 8 | TOUCHPAD=$(xinput list --name-only | grep -i touchpad | head -n 1) 9 | TOUCHSCREEN=$(xinput list --name-only | grep -Ei '(finger|touchscreen)' | head -n 1) 10 | TRANSFORM='Coordinate Transformation Matrix' 11 | 12 | usage() { 13 | >&2 printf '%s\n%s\n' \ 14 | 'Usage: rotate [n] [i] [l] [r]' \ 15 | 'No args: toggle [n] <-> [l]' 16 | exit 1 17 | } 18 | 19 | get_disp() { 20 | xrandr --listactivemonitors | \ 21 | while read -r _ _ _ disp ; do 22 | [ "$disp" ] && echo "$disp" 23 | done 24 | } 25 | 26 | normal() { 27 | xrandr --output "$(get_disp)" --rotate normal 28 | [ "$TOUCHPAD" ] && xinput set-prop "$TOUCHPAD" "$TRANSFORM" 1 0 0 0 1 0 0 0 1 29 | [ "$TOUCHSCREEN" ] && xinput set-prop "$TOUCHSCREEN" "$TRANSFORM" 1 0 0 0 1 0 0 0 1 30 | } 31 | 32 | inverted() { 33 | xrandr --output "$(get_disp)" --rotate inverted 34 | [ "$TOUCHPAD" ] && xinput set-prop "$TOUCHPAD" "$TRANSFORM" -1 0 1 0 -1 1 0 0 1 35 | [ "$TOUCHSCREEN" ] && xinput set-prop "$TOUCHSCREEN" "$TRANSFORM" -1 0 1 0 -1 1 0 0 1 36 | } 37 | 38 | left() { 39 | xrandr --output "$(get_disp)" --rotate left 40 | [ "$TOUCHPAD" ] && xinput set-prop "$TOUCHPAD" "$TRANSFORM" 0 -1 1 1 0 0 0 0 1 41 | [ "$TOUCHSCREEN" ] && xinput set-prop "$TOUCHSCREEN" "$TRANSFORM" 0 -1 1 1 0 0 0 0 1 42 | } 43 | 44 | right() { 45 | xrandr --output "$(get_disp)" --rotate right 46 | [ "$TOUCHPAD" ] && xinput set-prop "$TOUCHPAD" "$TRANSFORM" 0 1 0 -1 0 1 0 0 1 47 | [ "$TOUCHSCREEN" ] && xinput set-prop "$TOUCHSCREEN" "$TRANSFORM" 0 1 0 -1 0 1 0 0 1 48 | } 49 | 50 | toggle() { 51 | case $(xrandr --current --verbose | grep "^$(get_disp)") in 52 | *' normal '*) left ;; 53 | *) normal 54 | esac 55 | } 56 | 57 | case ${1#-} in 58 | h) usage ;; 59 | n) normal ;; 60 | i) inverted ;; 61 | l) left ;; 62 | r) right ;; 63 | *) toggle 64 | esac 65 | -------------------------------------------------------------------------------- /legacy/scrap: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # http://github.com/mitchweaver/bin 4 | # 5 | # scrap - SCReen cAPture 6 | # 7 | # Wrapper for both X11 and Wayland, working with both Gnome and wl-roots 8 | # 9 | # X11 deps: imagemagick, slop, xclip 10 | # Wayland deps: slurp, grim, wl-clipboard 11 | # softdeps: jpegoptim, a plumber via $PLUMBER 12 | # 13 | # -*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-* 14 | 15 | SCRAP_CACHE_DIR=${HOME}/tmp 16 | mkdir -p "$SCRAP_CACHE_DIR" 17 | PLUMBER=${PLUMBER:-opn} 18 | 19 | # don't run if already selecting (happens with keybinds) 20 | if pgrep -x slop >/dev/null ; then 21 | die "slop already running - exiting" 22 | fi 23 | 24 | usage() { 25 | >&2 cat < 29 | 30 | Options: 31 | --------------------------- 32 | [-n] no crop 33 | [-u] upload after capture 34 | [-r] re-open last scrap 35 | [-s] save last scrap 36 | [-o] open scrap after capture 37 | EOF 38 | exit 1 39 | } 40 | 41 | die() { >&2 printf '%s\n' "$*" ; exit 1 ; } 42 | 43 | while [ "$1" ] ; do 44 | case $1 in 45 | -h) 46 | usage 47 | ;; 48 | -n) 49 | nocrop=true 50 | ;; 51 | -u) 52 | upload=true 53 | ;; 54 | -f) 55 | open=true 56 | ;; 57 | -s) 58 | if [ -L /tmp/scrap-$USER.png ] ; then 59 | mv -- "$(readlink /tmp/scrap-$USER.png)" "${HOME}"/ 60 | fi 61 | exit 62 | ;; 63 | -r) 64 | $PLUMBER /tmp/scrap-$USER.png & 65 | exit 66 | ;; 67 | -*) 68 | # safely ignore invalid options 69 | ;; 70 | *) 71 | file="$*" 72 | set -- 73 | esac 74 | [ "$1" ] && shift 75 | done 76 | 77 | if [ "$file" ] ; then 78 | dir=${file%/*} 79 | [ "$dir" != "$file" ] && mkdir -p "$dir" 80 | else 81 | mkdir -p "$SCRAP_CACHE_DIR" 82 | count=$(find "$SCRAP_CACHE_DIR" -maxdepth 1 -type f -name 'scrap*' | wc -l) 83 | file="$SCRAP_CACHE_DIR/scrap-$count@$(date +%Y-%m-%d-%H-%M-%S).png" 84 | fi 85 | 86 | case $(wayland_or_x11) in 87 | wayland) 88 | # we are running gnome, we can use gnome-screenshot 89 | if pgrep -f gnome-shell >/dev/null ; then 90 | if [ "$nocrop" ] ; then 91 | gnome-screenshot -c -p -f "$file" 92 | else 93 | gnome-screenshot -c -a -p -f "$file" 94 | fi 95 | else 96 | if [ "$nocrop" ] ; then 97 | grim "$file" 98 | else 99 | if command -v slurp >/dev/null ; then 100 | geom=$(slurp 2>/dev/null) 101 | fi 102 | [ "$geom" ] || die "couldn't get geometry from slurp" 103 | grim -g "$geom" "$file" 104 | cat "$file" | wl-copy 105 | fi 106 | fi 107 | ;; 108 | *) 109 | if [ "$nocrop" ] ; then 110 | import -quiet -window root "$file" 111 | else 112 | if command -v slop >/dev/null ; then 113 | geom=$(slop -f '%wx%h+%x+%y' 2>/dev/null) 114 | fi 115 | [ "$geom" ] || die "couldn't get geometry from slop" 116 | # shellcheck disable=2086 117 | set -- -crop $geom "$file" 118 | import -quiet -window root "$@" 119 | fi 120 | esac 121 | 122 | if [ ! -f "$file" ] ; then 123 | die "Couldn't get screenshot for '$file'" 124 | fi 125 | 126 | if [ "$upload" ] ; then 127 | if command -v upl >/dev/null ; then 128 | url=$(upl "$file") 129 | else 130 | url=$(curl -sF "file=@$file" https://0x0.st 2>/dev/null) 131 | fi 132 | if [ "$url" ] ; then 133 | notify-send "${0##*/}: $url" 134 | printf '%s\n' "$url" 135 | 136 | case $(wayland_or_x11 ) in 137 | wayland) 138 | printf '%s\n' "$url" | wl-copy 139 | ;; 140 | x11) 141 | if [ "$upload" ] && [ "$url" ] ; then 142 | # copy url to clipboard 143 | if command -v xsel >/dev/null ; then 144 | printf '%s\n' "$url" | xsel -ip 145 | printf '%s\n' "$url" | xsel -is 146 | printf '%s\n' "$url" | xsel -ib 147 | fi 148 | fi 149 | ;; 150 | esac 151 | else 152 | notify-send "${0##*/}: failed to upload" 153 | die "failed to upload '$file'" 154 | fi 155 | 156 | 157 | fi 158 | 159 | # optimize file if available 160 | # if command -v jpegoptim >/dev/null ; then 161 | # jpegoptim -sq "$file" 162 | # fi 163 | 164 | [ "$open" ] && exec $PLUMBER "$file" 165 | 166 | -------------------------------------------------------------------------------- /legacy/square: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # http://github.com/mitchweaver/bin 4 | # 5 | # select a color with your mouse and open 6 | # a small square image with its #HEXHEX 7 | # 8 | # deps: color 9 | # 10 | # You can get color here: http://github.com/mitchweaver/color 11 | # 12 | 13 | dir=${XDG_CACHE_HOME:-~/.cache}/square 14 | mkdir -p "$dir" 15 | 16 | usage() { 17 | printf 'Usage: %s [-p]\n' "${0##*/}" 18 | exit 1 19 | } 20 | 21 | if [ "$1" ] ; then 22 | case $1 in 23 | -h|h) 24 | usage 25 | ;; 26 | -p|p) 27 | if command -v color >/dev/null ; then 28 | set -- "$(color | tee /dev/tty)" 29 | else 30 | >&2 echo "Install color first." 31 | exit 1 32 | fi 33 | ;; 34 | esac 35 | else 36 | read -r inp 37 | set -- "$inp" 38 | [ "$1" ] || usage 39 | fi 40 | 41 | # allow input w/o the hash 42 | case $1 in 43 | \#*) 44 | ;; 45 | *) 46 | set -- "#$1" 47 | esac 48 | 49 | if convert -size 100x100 xc:"$1" "$dir/$1.png" ; then 50 | nohup "${PLUMBER:-display}" "$dir/$1.png" >/dev/null 2>&1 & 51 | fi 52 | -------------------------------------------------------------------------------- /legacy/vol: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # http://github.com/mitchweaver/bin 4 | # 5 | # simple volume wrapper 6 | # 7 | # Linux - supports pipewire, alsa, pulseaudio 8 | # OpenBSD - supported via sndioctl 9 | # 10 | # =/=/=/=/=/=/=/=/=/=/=/=/=/=/=/=/=/=/=/=/=/=/=/= 11 | 12 | usage() { 13 | >&2 printf 'Usage: %s\n' "${0##*/} [i inc] [d dec] [s set] [m mute] [u unmute]" 14 | exit 15 | } 16 | 17 | case ${1#-} in 18 | h) 19 | usage 20 | ;; 21 | *) 22 | case $(uname) in 23 | OpenBSD) 24 | case ${1#-} in 25 | i) 26 | sndioctl -q output.mute=0 27 | sndioctl -q output.level=+"${VOL_ADJUSTMENT_AMOUNT:-0.03}" 28 | ;; 29 | d) 30 | sndioctl -q output.mute=0 31 | sndioctl -q output.level=-"${VOL_ADJUSTMENT_AMOUNT:-0.03}" 32 | ;; 33 | s) 34 | sndioctl -q output.mute=0 35 | sndioctl -q output.level=0."$2" 36 | ;; 37 | m) 38 | sndioctl -q output.mute=1 39 | ;; 40 | u) 41 | sndioctl -q output.mute=0 42 | ;; 43 | *) 44 | vol=$(sndioctl -n output.level) 45 | vol=${vol%?} 46 | vol=${vol#0.} 47 | vol=${vol#0} 48 | case $vol in 49 | 1.00) 50 | vol=100 51 | ;; 52 | 0) 53 | vol=0 54 | esac 55 | printf '%s\n' "$vol" 56 | esac 57 | ;; 58 | Linux) 59 | # use pulseaudio if available, note on fedora pacmd is a command but isnt used 60 | if command -v pacmd >/dev/null && ! command -v dnf >/dev/null ; then 61 | case ${1#-} in 62 | i) 63 | pactl set-sink-mute 0 false 64 | pactl set-sink-volume @DEFAULT_SINK@ +3% 65 | ;; 66 | d) 67 | pactl set-sink-mute 0 false 68 | pactl set-sink-volume @DEFAULT_SINK@ -3% 69 | ;; 70 | s) 71 | pactl set-sink-mute 0 false 72 | pactl set-sink-volume @DEFAULT_SINK@ "$2"% 73 | ;; 74 | *) 75 | sink=$(pacmd list-sinks | awk '/index:/{i++} /* index:/{print i; exit}') 76 | pacmd list-sinks | awk '/^\svolume:/{i++} i=='"$sink"'{print $5; exit}' 77 | esac 78 | elif command -v amixer >/dev/null ; then 79 | case ${1#-} in 80 | i) 81 | amixer --quiet set 'Master' unmute 82 | amixer --quiet set 'Master' 5%+ 83 | ;; 84 | d) 85 | amixer --quiet set 'Master' unmute 86 | amixer --quiet set 'Master' 5%- 87 | ;; 88 | s) 89 | amixer --quiet set 'Master' unmute 90 | amixer --quiet set 'Master' "$2"% 91 | ;; 92 | *) 93 | vol=$(amixer sget 'Master' | grep '%' | head -n 1) 94 | vol="${vol%%]*}" 95 | vol="${vol##*[}" 96 | printf '%s\n' "$vol" 97 | esac 98 | else 99 | >&2 echo "No pulseaudio pactl or alsa amixer detected." 100 | exit 1 101 | fi 102 | esac 103 | esac 104 | 105 | -------------------------------------------------------------------------------- /legacy/wallgen: -------------------------------------------------------------------------------- 1 | #!/bin/sh -e 2 | # 3 | # http://github.com/mitchweaver/bin 4 | # 5 | # generate a wallpaper with some static given a color #HEXHEX code 6 | # ======================================================================== 7 | 8 | if [ -z "$1" ] ; then 9 | if command -v color >/dev/null ; then 10 | set -- "$(color)" 11 | else 12 | >&2 echo "No argument provided and no colorpicker installed. Exiting." 13 | exit 1 14 | fi 15 | fi 16 | 17 | WALLGEN_DIR="${XDG_CACHE_HOME:-~/.cache}/wallgen" 18 | mkdir -p "$WALLGEN_DIR" 19 | 20 | count=$(find "$WALLGEN_DIR" -maxdepth 1 -type f -name '*.jpg' | wc -l) 21 | file="$WALLGEN_DIR/wallgen-$count.jpg" 22 | 23 | convert -size 128x128 xc:"$*" \ 24 | -separate -seed 1000 \ 25 | -attenuate 0.13 \ 26 | +noise gaussian \ 27 | -combine -colorspace sRGB "$file" 28 | 29 | echo "Created: $file" 30 | printf "Set as background? (y/n):" 31 | read -r ans 32 | case $ans in 33 | y) background -t "$file" 34 | esac 35 | -------------------------------------------------------------------------------- /legacy/yt: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # http://github.com/mitchweaver/bin 4 | # 5 | # search for and/or play youtube videos with mpv 6 | # 7 | # shellcheck disable=2086 8 | # 9 | 10 | usage() { 11 | >&2 printf \ 12 | 'Usage: %s [-s search] [-m music] [-d download] \n' \ 13 | "${0##*/}" 14 | exit 1 15 | } 16 | 17 | [ "$1" ] || usage 18 | 19 | case ${1#-} in 20 | h) 21 | usage 22 | ;; 23 | s) 24 | shift 25 | exec youtube-dl -e --default-search ytsearch8 \ 26 | -- "$(printf '%s\n' "$*" | tr ' ' '+')" 27 | ;; 28 | m) 29 | shift 30 | MPV_OPTS="$MPV_OPTS --no-video" 31 | YTDL_OPTS="-x" 32 | ;; 33 | d) 34 | shift 35 | exec youtube-dl "$YTDL_OPTS" \ 36 | -c -R 50 --geo-bypass --prefer-ffmpeg \ 37 | ytsearch:"$(printf '%s\n' "$*" | tr ' ' '+')" 38 | ;; 39 | esac 40 | 41 | exec mpv \ 42 | $MPV_OPTS \ 43 | --no-loop \ 44 | --script-opts=ytdl_hook-try_ytdl_first=yes \ 45 | -- ytdl://ytsearch:"$(printf '%s\n' "$*" | tr ' ' '+')" 46 | -------------------------------------------------------------------------------- /legacy/ytdlq: -------------------------------------------------------------------------------- 1 | #!/bin/sh -e 2 | # 3 | # http://github.com/mitchweaver/bin 4 | # 5 | # ytdlq - a little queue to download youtube videos 6 | # 7 | # deps: youtube-dl, detox 8 | # 9 | 10 | # -*-*- config -*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*- 11 | : "${YTDL_OPTS:='--prefer-ffmpeg -o %(title)s.%(ext)s'}" 12 | : "${YTDLQ_DIR:=~/.ytdlq}" 13 | queue=$YTDLQ_DIR/queue 14 | working=$YTDLQ_DIR/working 15 | completed=$YTDLQ_DIR/completed 16 | downloading=$YTDLQ_DIR/downloading 17 | logs=$YTDLQ_DIR/logs 18 | # -*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-* 19 | 20 | usage() { 21 | >&2 cat <"$log" 2>&1 57 | } 58 | 59 | start_daemon() { 60 | mkdir -p "$YTDLQ_DIR" 61 | touch "$queue" "$working" 62 | printf '%s\n' $$ > "${XDG_CACHE_HOME:-${HOME}/.cache}/${0##*/}.pid" 63 | 64 | while sleep 5 ; do 65 | if [ -s "$queue" ] ; then 66 | # sleep if no internet connection 67 | while ! ping -q -L -c 1 -s 1 youtube.com >/dev/null ; do 68 | sleep 30 69 | done 70 | 71 | read -r link <"$queue" 72 | { 73 | printf '%s\n' "$link" >> "$working" 74 | dl "$link" || printf '%s\n' "$link" >>"$queue".rej 75 | sed -i "/.*${link##*/}.*/d" "$working" 76 | } & 77 | sed -i '1d' "$queue" 78 | fi 79 | done 80 | } 81 | 82 | stop_daemon() { 83 | if [ -f "${XDG_CACHE_HOME:-${HOME}/.cache}/${0##*/}.pid" ] ; then 84 | read -r pid < "${XDG_CACHE_HOME:-${HOME}/.cache}/${0##*/}.pid" 85 | kill -0 "$pid" && kill -9 "$pid" 86 | fi 87 | } 88 | 89 | add() { 90 | [ "$1" ] || usage 91 | printf '%s\n' "$1" >>"$queue" 92 | } 93 | 94 | mass_add() { 95 | tmp=/tmp/$$.${0##*/} 96 | ${EDITOR:-vi} "$tmp" 97 | if [ "$tmp" ] ; then 98 | while read -r url ; do 99 | add "$url" 100 | done < "$tmp" 101 | rm "$tmp" 102 | fi 103 | } 104 | 105 | case ${1#-} in 106 | a) 107 | add "$2" 108 | ;; 109 | m|v) 110 | mass_add 111 | ;; 112 | d) 113 | start_daemon 114 | ;; 115 | q) 116 | stop_daemon 117 | ;; 118 | r) 119 | if [ -f "$queue".rej ] ; then 120 | cat "$queue".rej >> "$queue" 121 | rm "$queue".rej 122 | fi 123 | ;; 124 | *) 125 | usage 126 | esac 127 | -------------------------------------------------------------------------------- /legacy/ytknife: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # http://github.com/mitchweaver/bin 4 | # 5 | # ▐ ▌ ▗ ▗▀▖ 6 | # ▌ ▌▜▀ ▌▗▘▛▀▖▄ ▐ ▞▀▖ 7 | # ▚▄▌▐ ▖▛▚ ▌ ▌▐ ▜▀ ▛▀ 8 | # ▗▄▘ ▀ ▘ ▘▘ ▘▀▘▐ ▝▀▘ 9 | # 10 | # youtube-dl swiss army knife 11 | # 12 | # Originally written to view tags of youtube videos, 13 | # it will grow in features eventually as needs arise. 14 | # 15 | 16 | die() { >&2 printf 'Error: %s\n' "$*" ; exit 1 ; } 17 | 18 | usage() { 19 | >&2 cat </dev/null || die 'Missing dependency: jq' 43 | 44 | case $# in 45 | 1) 46 | case $1 in 47 | h|-h|*help) ;; 48 | *) die 'Not enough arguments.' 49 | esac 50 | esac 51 | 52 | while [ "$1" ] ; do 53 | case ${1#-} in 54 | h|*help) usage ;; 55 | dump) dumpinfo "$2" ; exit ;; 56 | c) dumpinfo "$2" | jq -r '.categories[]' ; shift ;; 57 | d) dumpinfo "$2" | jq -r '.upload_date' ; shift ;; 58 | i) dumpinfo "$2" | jq -r '.id' ; shift ;; 59 | l) dumpinfo "$2" | jq -r '.duration' ; shift ;; 60 | n) dumpinfo "$2" | jq -r '.thumbnail' ; shift ;; 61 | s) dumpinfo "$2" | jq -r '.description' ; shift ;; 62 | t) dumpinfo "$2" | jq -r '.title' ; shift ;; 63 | u) dumpinfo "$2" | jq -r '.uploader' ; shift ;; 64 | g) dumpinfo "$2" | jq -r '.tags[]' ; shift ;; 65 | esac 66 | shift 67 | done 68 | } 69 | 70 | main "$@" 71 | -------------------------------------------------------------------------------- /non-shell/README.md: -------------------------------------------------------------------------------- 1 | # non-shell 2 | 3 | These are not shell scripts and thus shouldn't be checked with 4 | shellcheck. 5 | -------------------------------------------------------------------------------- /non-shell/lower: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # http://github.com/mitchweaver/bin 4 | # 5 | # convert piped text to lowercase 6 | # 7 | 8 | tr '[:upper:]' '[:lower:]' 9 | -------------------------------------------------------------------------------- /non-shell/randmac: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # 3 | # generate a random valid mac address 4 | # 5 | 6 | import randmac 7 | print(randmac.RandMac("00:00:00:00:00:00")) 8 | -------------------------------------------------------------------------------- /non-shell/squeeze: -------------------------------------------------------------------------------- 1 | #!/usr/bin/awk -f 2 | # 3 | # http://github.com/mitchweaver/bin 4 | # 5 | # squeeze multiple blank lines into one 6 | # 7 | 8 | !NF {if (++n <= 1) print; next}; {n=0;print} 9 | -------------------------------------------------------------------------------- /non-shell/trim: -------------------------------------------------------------------------------- 1 | #!/usr/bin/awk -f 2 | # 3 | # https://github.com/mitchweaver/bin 4 | # 5 | # trim leading/trailing space from input 6 | # 7 | 8 | {$1=$1};1 9 | -------------------------------------------------------------------------------- /non-shell/upper: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # http://github.com/mitchweaver/bin 4 | # 5 | # convert piped text to uppercase 6 | # 7 | 8 | tr '[:lower:]' '[:upper:]' 9 | -------------------------------------------------------------------------------- /non-shell/urls: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # http://github.com/mitchweaver/bin 4 | # 5 | # grab urls from piped input or stdin 6 | # 7 | # ~ credit to z3bra 8 | # 9 | # note: reportedly doesn't work with all versions of grep 10 | # 11 | 12 | prot='[a-zA-Z]+://' 13 | host='[-a-zA-Z0-9._+]+' 14 | path='[-a-zA-Z0-9._+#=?&:;%/!~()]+' 15 | 16 | grep -Eo "$prot$host$path" 17 | --------------------------------------------------------------------------------