diffdir

23rd February 2017 at 5:38pm
Bash CodeSnippets
#!/bin/bash
# vim:ts=2:sw=2:tw=79

set -euo pipefail
shopt -s extglob
shopt -s nocasematch

now () {
  if [[ ${BASH_VERSINFO[0]} -ge 4 && ${BASH_VERSINFO[1]} -ge 2 ]] ; then
    printf "%(%s)T" -1
  else
    date +"%s"
  fi
}

last_list () {
  local path="$1"
  local latest=""
  local file
  for file in "${path%%/}"/* ; do
    if [[ -f "$file" && "${file##*/}" =~ ^([0-9]{11,})$ ]] ; then
      if [[ -z "$latest" || "${file##*/}" -gt "${latest##*/}" ]] ; then
        latest="$file"
      fi
    fi
  done
  echo -n "$latest"
}

main () {
  local path="${1:-}"
  if [[ $# -ne 1 || ! -d "$path" ]] ; then
    >&2 echo "${0##*/} <directory>"
    return 64
  fi

  local tmp="${TMPDIR:-/tmp}"
  local dir_md5="$(md5sum <<< "$(readlink -f "$path")")"
  dir_md5="${dir_md5%% *}"
  tmp="${tmp%%/}/${0##*/}.$dir_md5"

  local curr_list="$(now)$(printf "%-.10d" "$$")"
  local last_list="$(last_list "$tmp")"

  mkdir -p "$tmp"
  ls -1 "$path" | sort | gzip > "$tmp/$curr_list"

  if [[ -z "$last_list" ]] ; then
    diff /dev/null <(zcat "$tmp/$curr_list") | grep -v '^[^<>]'
  else
    diff <(zcat "$last_list") <(zcat "$tmp/$curr_list") | grep -v '^[^<>]'
  fi
}

main "$@"