Skip to content

Instantly share code, notes, and snippets.

@felixbuenemann
Created November 15, 2020 20:17
Show Gist options
  • Select an option

  • Save felixbuenemann/e4df9485111dbaefd2f3ecabff5bcb20 to your computer and use it in GitHub Desktop.

Select an option

Save felixbuenemann/e4df9485111dbaefd2f3ecabff5bcb20 to your computer and use it in GitHub Desktop.

Revisions

  1. felixbuenemann created this gist Nov 15, 2020.
    105 changes: 105 additions & 0 deletions pkg-remove
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,105 @@
    #!/bin/sh
    # pkg-remove removes macOS packages using the receipt
    # Copyright: 2020 by Felix Buenemann
    # License: MIT
    set -eo pipefail
    volume=/
    dryrun=false
    force=false
    for arg in "$@"; do
    case $arg in
    --volume=*)
    volume=${arg#*=}
    shift
    ;;
    -v|--volume)
    shift
    volume=$1
    shift
    ;;
    -n|--dry-run)
    force=true
    dryrun=true
    shift
    ;;
    -f|--force)
    force=true
    shift
    ;;
    -h|--help)
    echo "Usage: $0 [-n|--dry-run] [v|--volume VOLUME] PKGID [..PKGID]"
    exit 0
    ;;
    -*)
    echo "Unknown option: $arg (see -h for help)" >/dev/stderr
    exit 1
    ;;
    esac
    done

    if $dryrun; then
    echo "Dry-run active, simulating changes. Nothing will be removed!" >/dev/stderr
    fi

    for pkgid in "$@"; do
    location=`pkgutil --volume "$volume" --pkg-info "$pkgid" | \
    awk -F': ' '/^(volume|location):/{printf $2}' | tr -s /`

    root=`pkgutil --volume "$volume" --only-dirs --files "$pkgid" | head -n1 ||:`
    echo $root

    if [ ! -d "$location" ]; then
    echo "Package $pkgid install location '$location' doesn't exist" >/dev/stderr
    else
    if ! $force; then
    read -p "Remove package $pkgid from '$location'? (y/N) " remove
    if [ "$remove" != "y" ]; then
    echo "Skipping $pkgid" >/dev/stderr
    continue
    fi
    else
    echo "Removing package $pkgid from '$location'" >/dev/stderr
    fi

    extra=
    if [ -d "$location/$root/Contents/_MASReceipt" ]; then
    echo "Detected Mac AppStore receipt, adding to deleted files" >/dev/stderr
    extra="$root/Contents/_MASReceipt\n$root/Contents/_MASReceipt/receipt\n"
    fi

    if $dryrun; then
    (pkgutil --volume "$volume" --files "$pkgid" && printf "$extra") \
    | tail -r \
    | awk "{ printf \"$location/%s%c\", \$0, 0 } END { printf \"$location\" }" \
    | tr -s / \
    | xargs -0 -n1 echo rm -df
    else
    # use relative paths so we can do more deletes in a single rm call
    (pkgutil --volume "$volume" --files "$pkgid" && printf "$extra") \
    | tail -r \
    | tr '\n' '\0' \
    | (cd "$location" && sudo xargs -0 rm -df)
    # ignore errors when removing location (eg. /Applications)
    sudo rm -df "$location" 2>/dev/null ||:
    fi
    fi

    if ! $dryrun && [ "$root" != "" ] && [ -d "$location/$root" ]; then
    echo "Package root directory '$location/$root' still exists!" >/dev/stderr
    continue
    fi

    if ! $force; then
    read -p "Remove package $pkgid install receipt? (y/N) " remove
    if [ "$remove" != "y" ]; then
    echo "Skipping $pkgid" >/dev/stderr
    continue
    fi
    else
    echo "Removing package $pkgid install receipt" >/dev/stderr
    fi

    if ! $dryrun; then
    sudo pkgutil --volume "$volume" --forget "$pkgid"
    fi
    done