Nifty tools for my system

I've come across multiple neat tools. Given all of my configs are literate programming configs, this sets up those scripts. Otherwise, I'd either not have those tools, or I'd have two processes for getting my dotfiles setup.


sudo aptitude install imagemagick


This tool does a simple screenshot using imagemagick's import. It's easy to invoke from dmenu as snapshot my-thing and it ends up on my desktop.

if [[ "$name" == *"png"* ]]; then
    import ~/Desktop/$name
    import ~/Desktop/$name.png


Uploads an image to imgur.

# imgur script by Bart Nagel <>
# version 4
# I release this into the public domain. Do with it what you will.

# Required: curl
# Optional: xsel or xclip for automatically putting the URLs on the X selection 
# for easy pasting
# Instructions:
# Put it somewhere in your path and maybe rename it:
#       mv ~/Downloads/ ~/bin/imgur
# Make it executable:
#       chmod +x ~/bin/imgur
# Optional, since Alan kindly provided an API key for this script: stick your 
# API key in the top:
#       vim ~/bin/imgur
# Upload an image:
#       imgur images/hilarious/manfallingover.jpg
# Upload multiple images:
#       imgur images/delicious/cake.png images/exciting/bungeejump.jpg
# The URLs will be displayed (and the delete page's URLs will be displayed on 
# stderr). If you have xsel or xclip the URLs will also be put on the X 
# selection, which you can usually paste with a middle click.

# API Key provided by

# function to output usage instructions
function usage {
        echo "Usage: $(basename $0) <filename> [<filename> [...]]" >&2
        echo "Upload images to imgur and output their new URLs to stdout. Each one's" >&2
        echo "delete page is output to stderr between the view URLs." >&2
        echo "If xsel or xclip is available, the URLs are put on the X selection for" >&2
        echo "easy pasting." >&2

# check API key has been entered
if [ "$apikey" = "Your API key" ]; then
        echo "You first need to edit the script and put your API key in the variable near the top." >&2
        exit 15

# check arguments
if [ "$1" = "-h" -o "$1" = "--help" ]; then
        exit 0
elif [ $# == 0 ]; then
        echo "No file specified" >&2
        exit 16

# check curl is available
type curl >/dev/null 2>/dev/null || {
        echo "Couln't find curl, which is required." >&2
        exit 17


# loop through arguments
while [ $# -gt 0 ]; do

        # check file exists
        if [ ! -f "$file" ]; then
                echo "file '$file' doesn't exist, skipping" >&2

        # upload the image
        response=$(curl -F "key=$apikey" -H "Expect: " -F "image=@$file" \
        # the "Expect: " header is to get around a problem when using this through 
        # the Squid proxy. Not sure if it's a Squid bug or what.
        if [ $? -ne 0 ]; then
                echo "Upload failed" >&2
        elif [ $(echo $response | grep -c "<error_msg>") -gt 0 ]; then
                echo "Error message from imgur:" >&2
                echo $response | sed -r 's/.*<error_msg>(.*)<\/error_msg>.*/\1/' >&2

        # parse the response and output our stuff
        url=$(echo $response | sed -r 's/.*<original_image>(.*)<\/original_image>.*/\1/')
        deleteurl=$(echo $response | sed -r 's/.*<delete_page>(.*)<\/delete_page>.*/\1/')
        echo $url
        echo "Delete page: $deleteurl" >&2

        # append the URL to a string so we can put them all on the clipboard later

# put the URLs on the clipboard if we have xsel or xclip
if [ $DISPLAY ]; then
        { type xsel >/dev/null 2>/dev/null && echo -n $clip | xsel; } \
                || { type xclip >/dev/null 2>/dev/null && echo -n $clip | xclip; } \
                || echo "Haven't copied to the clipboard: no xsel or xclip" >&2
        echo "Haven't copied to the clipboard: no \$DISPLAY" >&2

if $errors; then
        exit 1

timestamp conversion

I need to convert epochs all the time from log diving. Thanks to Aaron Flatten for the script.

# > epoch # Return the current timestamp
# > epoch <number> # Convert the numeric unix timestamp to a readable date string
# > epoch <str> # Converts the readable date string to a timestamp (supports a few different formats, including ISO-8601)
# via Aaron Flatten

if [ $# -eq 0 ]; then
  date +%s
elif [[ $1 == *[-T:Z]* ]]; then
  echo $1 | ruby -e "require 'time'; puts Time.parse(STDIN.first).to_i"
  if [[ $1 -gt 1000000000000 ]]; then
    VAL=`echo $1 / 1000 | bc`
  date -d "UTC 1970-01-01 $VAL secs"


When doing some code analysis suggested by the talk Sandi Metz gave at DeconstructConf 2018, I needed to figure out how to calculate the churn of a particular file. This script helps in that regard.

# Written by Corey Haines
# Scriptified by Gary Bernhardt
# Put this anywhere on your $PATH (~/bin is recommended). Then git will see it
# and you'll be able to do `git churn`.
# Show churn for whole repo:
#   $ git churn
# Show churn for specific directories:
#   $ git churn app lib
# Show churn for a time range:
#   $ git churn --since='1 month ago'
# (These are all standard arguments to `git log`.)

set -e
git log --all -M -C --name-only --format='format:' "$@" | sort | grep -v '^$' | uniq -c | sort -n | awk 'BEGIN {print "count\tfile"} {print $1 "\t" $2}'

Cleaning up old kernels

Sometimes my ubuntu laptop gets a full boot partition. This script will get rid of the unused kernels. This may be a terrible idea, because I've definetely had kernels that caused unhappy boots, but it's better than apt failing because there's no diskspace on the boot partition.

sudo dpkg --list 'linux-image*' \
        | awk '{ if ($1=="ii") print $2}' \
        | grep -v `uname -r` \
        | xargs sudo apt-get purge

sudo apt autoremove -y
sudo update-grub

Toggle headphones mode

In Ubuntu, there's some weirdness with bluetooth headphones where you can either choose HSP mode which offers microphone support and 8-bit quality audio or you can have A2DP Sink, which offers CD quality audio and no microphone. This command swaps between them.

#!/bin/bash -x
function get_headphones_index() {
  echo $(pacmd list-cards | grep bluez_card -B1 | grep index | awk '{print $2}')

function _set_headphones_profile() {
  local profile=${1}
  pacmd set-card-profile $(get_headphones_index) ${profile}

function get_headphones_profile() {
  pacmd list-cards | grep bluez_card -A20 | grep "active profile" | tr '<>' ' ' | awk '{print $3}'

function set_headphones_profile_a2dp_sink() {
  _set_headphones_profile "a2dp_sink"
  echo "Bluetooth headphones a2dp_sink"

function set_headphones_profile_hsp() {
  _set_headphones_profile "headset_head_unit"
  echo "Bluetooth headphones headset_head_unit"

function main() {
  if [ $(get_headphones_profile) == "headset_head_unit" ]; then

© 2012 - 2020 · Home — Theme Simpleness