Skip to content

Instantly share code, notes, and snippets.

@mdaniel
Last active May 12, 2016 17:58
Show Gist options
  • Save mdaniel/1e9b1c26797aed3ce6d4 to your computer and use it in GitHub Desktop.
Save mdaniel/1e9b1c26797aed3ce6d4 to your computer and use it in GitHub Desktop.
Uninstall OS X packages using pkgutil manifests
#! /bin/bash
# can't -e because of all the potentially missing files/dirs
# and rm(dir) executions
set -u
args=`getopt dfn $*`
if [ $? != 0 ]; then
echo "Usage: $0 [-n] [-f|-d[d]] pkg-id" >&2
exit 1
fi
set -- $args
unset args
do_files=0
do_dirs=0
dry_run=''
for i
do
case "$i" in
-f)
do_files=$(( $do_files + 1 ))
shift
;;
-d)
do_dirs=$(( $do_dirs + 1 ))
shift
;;
-n)
dry_run=echo
shift
;;
--)
shift
break
;;
esac
done
PKGID="$1"
PKG_ROOT="$(pkgutil --pkg-info "$PKGID" \
| awk -F: '/location:/{print $2}' \
| sed -e 's,^[ \t]*,/,')"
join_paths_0() {
r="$1"
while [ 1 == 1 ]; do
read X || break
p="$r/$X"
if [ ! -e "$p" ]; then
echo "File/Dir is 404: $p" >&2
# return 1
else
printf "%s\000" "$p"
fi
done
}
if [ $do_files -gt 0 ]; then
pkgutil --only-files --files "$PKGID" \
| join_paths_0 "$PKG_ROOT" \
| xargs -0 $dry_run rm -v
RC=$?
elif [ $do_dirs -gt 0 ]; then
pkgutil --only-dirs --files "$PKGID" \
| sort -r \
| join_paths_0 "$PKG_ROOT" \
| xargs -0 $dry_run rmdir
RC=$?
LAST_DIR=$(pkgutil --only-dirs --files "$PKGID" \
| sort -r \
| tail -1)
if [ -d "$PKG_ROOT/$LAST_DIR" ]; then
echo 'Left-over items:'
# -d = depth first
# -x = only one device
find -d -x "$PKG_ROOT/$LAST_DIR" -not -type d
if [ $do_dirs -gt 1 ]; then
printf 'Delete them? '
read X || :
if [ "${X:-}" == "y" ]; then
$dry_run find -d -x "$PKG_ROOT/$LAST_DIR" -not -type d -delete
fi
fi
fi
fi
# echo "RC=$RC"
exit $RC
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment