No longer needs sourced utility file

This commit is contained in:
Nathaniel Landau
2016-02-26 20:14:06 -05:00
parent d5f46e276d
commit cb23b6a0ed

336
bin/trash
View File

@@ -1,107 +1,20 @@
#!/usr/bin/env bash #!/usr/bin/env bash
# ##################################################
#
# Taken from: https://github.com/morgant/tools-osx
#
# Trash allows trashing of files instead of tempting fate with rm. Correctly handles
# trashing files on other volumes, uses the same filename renaming scheme as Finder
# for duplicate file names, can list trash contents w/disk usage summary, and empty
# trash (including securely) w/confirmation. Does not require Finder to be running.
#
version="1.0.0" # Sets version variable
#
scriptTemplateVersion="1.4.1" # Version of scriptTemplate.sh that this script is based on
#
# HISTORY:
#
# * 2015-06-20 - v1.0.0 - First Creation
#
# ##################################################
# Provide a variable with the location of this script.
scriptPath="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
# Source Scripting Utilities
# -----------------------------------
# These shared utilities provide many functions which are needed to provide
# the functionality in this boilerplate. This script will fail if they can
# not be found.
# -----------------------------------
utilsLocation="${scriptPath}/../lib/utils.sh" # Update this path to find the utilities.
if [ -f "${utilsLocation}" ]; then
source "${utilsLocation}"
else
echo "Please find the file util.sh and add a reference to it in this script. Exiting."
exit 1
fi
# trapCleanup Function
# -----------------------------------
# Any actions that should be taken if the script is prematurely
# exited. Always call this function at the top of your script.
# -----------------------------------
function trapCleanup() {
echo ""
if is_dir "${tmpDir}"; then
rm -r "${tmpDir}"
fi
die "Exit trapped." # Edit this if you like.
}
# Set Flags
# -----------------------------------
# Flags which can be overridden by user input.
# Default values are below
# -----------------------------------
quiet=false
printLog=false
verbose=false
force=false
strict=false
debug=false
list=false
emptyTrash=false
secureEmpty=false
args=()
# Set Temp Directory
# -----------------------------------
# Create temp directory with three random numbers and the process ID
# in the name. This directory is removed automatically at exit.
# -----------------------------------
tmpDir="/tmp/${scriptName}.$RANDOM.$RANDOM.$RANDOM.$$"
(umask 077 && mkdir "${tmpDir}") || {
die "Could not create temporary directory! Exiting."
}
# Check for Dependencies
# -----------------------------------
# Arrays containing package dependencies needed to execute this script.
# The script will fail if dependencies are not installed. For Mac users,
# most dependencies can be installed automatically using the package
# manager 'Homebrew'. Mac applications will be installed using
# Homebrew Casks. Ruby and gems via RVM.
# -----------------------------------
homebrewDependencies=()
caskDependencies=()
gemDependencies=()
function mainScript() { function mainScript() {
############## Begin Script Here ################### local user
#################################################### local uid
local finder_pid
# global variables user=$(whoami)
local user=$(whoami) uid=$(id -u "$user")
local uid=$(id -u "$user") finder_pid=$(ps -u "$user" | grep /System/Library/CoreServices/Finder.app | grep -v grep | awk '{print $1}')
local finder_pid=$(ps -u "$user" | grep /System/Library/CoreServices/Finder.app | grep -v grep | awk '{print $1}')
v='' if ${verbose}; then v="-v"; fi
# determine whether we can script the Finder or not
function have_scriptable_finder() { function have_scriptable_finder() {
# We must have a valid PID for Finder, plus we cannot be in `screen` (another thing that's broken) # Determine whether we can script the Finder or not
# We must have a valid PID for Finder, plus we cannot be in
# `screen` (another thing that's broken)
if [[ (${finder_pid} -gt 1) && ("$STY" == "") ]]; then if [[ (${finder_pid} -gt 1) && ("$STY" == "") ]]; then
true true
else else
@@ -109,21 +22,20 @@ function have_scriptable_finder() {
fi fi
} }
##
## Convert a relative path to an absolute path.
##
## From http://github.com/morgant/realpath
##
## @param string the string to converted from a relative path to an absolute path
## @returns Outputs the absolute path to STDOUT, returns 0 if successful or 1 if an error (esp. path not found).
##
function realpath() { function realpath() {
local success=true # Convert a relative path to an absolute path.
#
# From http://github.com/morgant/realpath
#
# @param string the string to converted from a relative path to an absolute path
# @returns Outputs the absolute path to STDOUT, returns 0 if successful or 1 if
# an error (esp. path not found).
local successPath=true
local path="$1" local path="$1"
# make sure the string isn't empty as that implies something in further logic # make sure the string isn't empty as that implies something in further logic
if [ -z "$path" ]; then if [ -z "$path" ]; then
success=false successPath=false
else else
# start with the file name (sans the trailing slash) # start with the file name (sans the trailing slash)
path="${path%/}" path="${path%/}"
@@ -147,13 +59,13 @@ function realpath() {
# attempt to change to the directory # attempt to change to the directory
if ! cd "${directory}" &>/dev/null ; then if ! cd "${directory}" &>/dev/null ; then
success=false successPath=false
fi fi
if ${success}; then if ${success}; then
# does the filename exist? # does the filename exist?
if [[ ( -n "${file_basename}" ) && ( ! -e "${file_basename}" ) ]]; then if [[ ( -n "${file_basename}" ) && ( ! -e "${file_basename}" ) ]]; then
success=false successPath=false
fi fi
# get the absolute path of the current directory & change back to previous directory # get the absolute path of the current directory & change back to previous directory
@@ -172,18 +84,25 @@ function realpath() {
fi fi
fi fi
${success} ${successPath}
} }
function listTrash() { function listTrash() {
local num_volumes
local total_blocks
local blocks
local size
num_volumes=0 num_volumes=0
total_blocks=0 total_blocks=0
notice "Listing items in Trash"
# list file contents & calculate size for user's .Trash folder # list file contents & calculate size for user's .Trash folder
if find "/Users/${user}/.Trash" -depth 1 ! -depth 0; then if find "/Users/${user}/.Trash" -depth 1 ! -depth 0; then
num_volumes=$(( $num_volumes + 1 )) num_volumes=$(( num_volumes + 1 ))
blocks=$(du -cs "/Users/${user}/.Trash" | tail -n 1 | cut -f 1) blocks=$(du -cs "/Users/${user}/.Trash" | tail -n 1 | cut -f 1)
total_blocks=$(( $total_blocks + $blocks )) total_blocks=$(( total_blocks + blocks ))
fi fi
# list file contents & calculate size for volume-specific .Trashes folders # list file contents & calculate size for volume-specific .Trashes folders
for file in /Volumes/*; do for file in /Volumes/*; do
@@ -191,19 +110,19 @@ function listTrash() {
folder="${file}/.Trashes/${uid}" folder="${file}/.Trashes/${uid}"
if [ -d "${folder}" ]; then if [ -d "${folder}" ]; then
if find "${folder}" -depth 1 ! -depth 0; then if find "${folder}" -depth 1 ! -depth 0; then
num_volumes=$(( ${num_volumes} + 1 )) num_volumes=$(( num_volumes + 1 ))
blocks=$(du -cs "${folder}" | tail -n 1 | cut -f 1) blocks=$(du -cs "${folder}" | tail -n 1 | cut -f 1)
total_blocks=$(( ${total_blocks} + ${blocks} )) total_blocks=$(( total_blocks + blocks ))
fi fi
fi fi
fi fi
done done
# convert blocks to human readable size # convert blocks to human readable size
size=0 size=0
if (( ${total_blocks} >= 2097152 )); then if (( total_blocks >= 2097152 )); then
size=$(bc <<< "scale=2; ${total_blocks} / 2097152") size=$(bc <<< "scale=2; ${total_blocks} / 2097152")
size="${size}GB" size="${size}GB"
elif (( ${total_blocks} >= 2048 )); then elif (( total_blocks >= 2048 )); then
size=$(bc <<< "scale=2; ${total_blocks} / 2048") size=$(bc <<< "scale=2; ${total_blocks} / 2048")
size="${size}MB" size="${size}MB"
else else
@@ -211,27 +130,25 @@ function listTrash() {
size="${size}K" size="${size}K"
fi fi
info "${size} across ${num_volumes} volume(s)." info "${size} across ${num_volumes} volume(s)."
safeExit
} }
function emptyTheTrash() { function emptyTheTrash() {
# determine if we can tell Finder to empty trash via AppleScript # Determine if we can tell Finder to empty trash via AppleScript
if have_scriptable_finder; then if have_scriptable_finder; then
notice "Telling Finder to empty trash..." notice "Telling Finder to empty trash..."
if /usr/bin/osascript -e "tell application \"Finder\" to empty trash" ; then if /usr/bin/osascript -e "tell application \"Finder\" to empty trash" ; then
success "Trash has been emptied." success "Trash has been emptied"
safeExit safeExit
else else
die "Unable to empty trash." die "Unable to empty trash"
fi fi
# if Finder isn't scriptable, we'll manually empty the trash ourselves # If Finder isn't scriptable, we'll manually empty the trash ourselves
else else
# confirm that the user wants to empty the trash # Confirm that the user wants to empty the trash
seek_confirmation "Are you sure you want to empty the trash (this cannot be undone)?" seek_confirmation "Are you sure you want to empty the trash (this cannot be undone)?"
if is_confirmed; then if is_confirmed; then
notice "Emptying trash..." notice "Emptying trash..."
# delete the contents of user's .Trash folder # delete the contents of user's .Trash folder
if [[ ${verbose} == "1" ]]; then v="-v"; fi
find "/Users/${user}/.Trash" -depth 1 ! -depth 0 -print0 | xargs -0 rm $v -r find "/Users/${user}/.Trash" -depth 1 ! -depth 0 -print0 | xargs -0 rm $v -r
# delete the contents of the volume-specific .Trashes folders # delete the contents of the volume-specific .Trashes folders
for file in /Volumes/*; do for file in /Volumes/*; do
@@ -242,9 +159,8 @@ function emptyTheTrash() {
fi fi
fi fi
done done
success "Trash has been emptied." success "Trash has been emptied"
fi fi
safeExit
fi fi
} }
@@ -260,7 +176,6 @@ function secureEmptyTheTrash() {
fi fi
# if Finder isn't scriptable, we'll manually empty the trash ourselves # if Finder isn't scriptable, we'll manually empty the trash ourselves
else else
if [[ ${verbose} == "1" ]]; then v="-v"; fi
# confirm that the user wants to securely empty the trash # confirm that the user wants to securely empty the trash
seek_confirmation "Are you sure you want to securely empty the trash (this REALLY cannot be undone)?" seek_confirmation "Are you sure you want to securely empty the trash (this REALLY cannot be undone)?"
if is_confirmed; then if is_confirmed; then
@@ -277,17 +192,14 @@ function secureEmptyTheTrash() {
done done
success "Trash has been securely emptied." success "Trash has been securely emptied."
fi fi
safeExit
fi fi
} }
function trashAFile() { function trashAFile() {
if [[ ${verbose} == "1" ]]; then v="-v"; fi
# Iterate over all files passed by user # Iterate over all files passed by user
for userFile in "${args[@]}"; do for userFile in "${args[@]}"; do
if [ ! -e "${userFile}" ]; then if [ ! -e "${userFile}" ]; then
warning "${userFile}: No such file or directory." warning "${userFile}: No such file or directory"
continue continue
fi fi
# determine if we'll tell Finder to trash the file via AppleScript (very easy, plus free undo # determine if we'll tell Finder to trash the file via AppleScript (very easy, plus free undo
@@ -306,11 +218,10 @@ function trashAFile() {
fi fi
verbose "Telling Finder to trash '${file}'..." verbose "Telling Finder to trash '${file}'..."
if /usr/bin/osascript -e "tell application \"Finder\" to delete POSIX file \"$file\"" &>/dev/null; then if /usr/bin/osascript -e "tell application \"Finder\" to delete POSIX file \"$file\"" &>/dev/null; then
#if osascript -e "tell app \"Finder\" to delete POSIX file \"${file}\"" &>/dev/null; then
success "'${userFile}' moved to trash" success "'${userFile}' moved to trash"
else else
warning "'${userFile}' not moved to trash" warning "'${userFile}' not moved to trash"
safeExit continue
fi fi
# Finder isn't available for this user, so don't rely on it (we'll do all the dirty work ourselves) # Finder isn't available for this user, so don't rely on it (we'll do all the dirty work ourselves)
else else
@@ -352,23 +263,85 @@ function trashAFile() {
done done
} }
# run functions if ${list}; then listTrash; safeExit; fi
if ${list}; then listTrash; fi if ${emptyTrash}; then emptyTheTrash; safeExit; fi
if ${emptyTrash}; then emptyTheTrash; fi if ${secureEmpty}; then secureEmptyTheTrash; safeExit; fi
if ${secureEmpty}; then secureEmptyTheTrash; fi # Default behavior without flags is to delete a file
trashAFile trashAFile
####################################################
############### End Script Here ####################
} }
############## Begin Options and Usage ################### function trapCleanup() {
# trapCleanup Function
# -----------------------------------
# Any actions that should be taken if the script is prematurely
# exited. Always call this function at the top of your script.
# -----------------------------------
echo ""
# Delete temp files, if any
if [ -d "${tmpDir}" ] ; then
rm -r "${tmpDir}"
fi
die "Exit trapped."
}
function safeExit() {
# safeExit
# -----------------------------------
# Non destructive exit for when script exits naturally.
# Usage: Add this function at the end of every script.
# -----------------------------------
# Delete temp files, if any
if [ -d "${tmpDir}" ] ; then
rm -r "${tmpDir}"
fi
trap - INT TERM EXIT
exit
}
# Set Flags
# -----------------------------------
# Flags which can be overridden by user input.
# Default values are below
# -----------------------------------
list=false
emptyTrash=false
secureEmpty=false
quiet=false
printLog=false
verbose=false
force=false
strict=false
debug=false
args=()
# Set Temp Directory
# -----------------------------------
# Create temp directory with three random numbers and the process ID
# in the name. This directory is removed automatically at exit.
# -----------------------------------
tmpDir="/tmp/${scriptName}.$RANDOM.$RANDOM.$RANDOM.$$"
(umask 077 && mkdir "${tmpDir}") || {
die "Could not create temporary directory! Exiting."
}
# Logging
# -----------------------------------
# Log is only used when the '-l' flag is set.
#
# To never save a logfile change variable to '/dev/null'
# Save to Desktop use: $HOME/Desktop/${scriptBasename}.log
# Save to standard user log location use: $HOME/Library/Logs/${scriptBasename}.log
# -----------------------------------
logFile="${HOME}/Library/Logs/${scriptBasename}.log"
# Options and Usage
# -----------------------------------
# Print usage # Print usage
usage() { usage() {
echo -n " echo -n "${scriptName} [OPTION]... [FILE]...
${scriptName} [OPTION]... [FILE]...
${bold}Trash${reset} allows MacOS trashing of files instead of tempting fate with ${bold}rm${reset}. ${bold}Trash${reset} allows MacOS trashing of files instead of tempting fate with ${bold}rm${reset}.
Anything deleted with Trash will be moved to the native MacOS trash folder. Anything deleted with Trash will be moved to the native MacOS trash folder.
@@ -385,7 +358,9 @@ usage() {
-l , --list List trash contents -l , --list List trash contents
-e, --empty Empty trash contents -e, --empty Empty trash contents
-s, --secure Secure empty trash contents -s, --secure Secure empty trash contents
--force Skip all user interaction. Implied 'Yes' to all actions. --force Skip all user interaction. Implied 'Yes' to all actions.
--log Print log to file
-q, --quiet Quiet (no output) -q, --quiet Quiet (no output)
-v, --verbose Output more information. (Items echoed to 'verbose') -v, --verbose Output more information. (Items echoed to 'verbose')
-d, --debug Runs script in BASH debug mode (set -x) -d, --debug Runs script in BASH debug mode (set -x)
@@ -432,7 +407,8 @@ unset options
# Print help if no arguments were passed. # Print help if no arguments were passed.
# Uncomment to force arguments when invoking the script # Uncomment to force arguments when invoking the script
[[ $# -eq 0 ]] && set -- "--help" # -------------------------------------
# [[ $# -eq 0 ]] && set -- "--help"
# Read the options and set stuff # Read the options and set stuff
while [[ $1 = -?* ]]; do while [[ $1 = -?* ]]; do
@@ -442,8 +418,11 @@ while [[ $1 = -?* ]]; do
-l|--list) list=true ;; -l|--list) list=true ;;
-s|--secure) secureEmpty=true ;; -s|--secure) secureEmpty=true ;;
-e|--empty) emptyTrash=true ;; -e|--empty) emptyTrash=true ;;
-v|--verbose) verbose=true ;; -v|--verbose) verbose=true ;;
--log) printLog=true ;;
-q|--quiet) quiet=true ;; -q|--quiet) quiet=true ;;
-s|--strict) strict=true;;
-d|--debug) debug=true;; -d|--debug) debug=true;;
--force) force=true ;; --force) force=true ;;
--endopts) shift; break ;; --endopts) shift; break ;;
@@ -455,18 +434,59 @@ done
# Store the remaining part as arguments. # Store the remaining part as arguments.
args+=("$@") args+=("$@")
############## End Options and Usage ###################
# Logging and Colors
# -----------------------------------------------------
# Here we set the colors for our script feedback.
# Example usage: success "sometext"
#------------------------------------------------------
# Set Colors
bold=$(tput bold)
reset=$(tput sgr0)
purple=$(tput setaf 171)
red=$(tput setaf 1)
green=$(tput setaf 76)
tan=$(tput setaf 3)
blue=$(tput setaf 38)
underline=$(tput sgr 0 1)
function _alert() {
if [ "${1}" = "emergency" ]; then local color="${bold}${red}"; fi
if [ "${1}" = "error" ] || [ "${1}" = "warning" ]; then local color="${red}"; fi
if [ "${1}" = "success" ]; then local color="${green}"; fi
if [ "${1}" = "debug" ]; then local color="${purple}"; fi
if [ "${1}" = "header" ]; then local color="${bold}""${tan}"; fi
if [ "${1}" = "input" ]; then local color="${bold}"; printLog="0"; fi
if [ "${1}" = "info" ] || [ "${1}" = "notice" ]; then local color=""; fi
# Don't use colors on pipes or non-recognized terminals
if [[ "${TERM}" != "xterm"* ]] || [ -t 1 ]; then color=""; reset=""; fi
# ############# ############# ############# # Print to $logFile
# ## TIME TO RUN THE SCRIPT ## if ${printLog}; then
# ## ## echo -e "$(date +"%m-%d-%Y %r") $(printf "[%9s]" "${1}") ${_message}" >> "${logFile}";
# ## You shouldn't need to edit anything ## fi
# ## beneath this line ##
# ## ## # Print to console when script is not 'quiet'
# ############# ############# ############# if ${quiet}; then
return
else
echo -e "$(date +"%r") ${color}$(printf "[%9s]" "${1}") ${_message}${reset}";
fi
}
function die () { local _message="${*} Exiting."; echo "$(_alert emergency)"; safeExit;}
function error () { local _message="${*}"; echo "$(_alert error)"; }
function warning () { local _message="${*}"; echo "$(_alert warning)"; }
function notice () { local _message="${*}"; echo "$(_alert notice)"; }
function info () { local _message="${*}"; echo "$(_alert info)"; }
function debug () { local _message="${*}"; echo "$(_alert debug)"; }
function success () { local _message="${*}"; echo "$(_alert success)"; }
function input() { local _message="${*}"; echo -n "$(_alert input)"; }
function header() { local _message="========== ${*} ========== "; echo "$(_alert header)"; }
# Log messages when verbose is set to "true"
verbose() { if ${verbose}; then debug "$@"; fi }
# Trap bad exits with your cleanup function # Trap bad exits with your cleanup function
trap trapCleanup EXIT INT TERM trap trapCleanup EXIT INT TERM
@@ -478,23 +498,17 @@ IFS=$'\n\t'
set -o errexit set -o errexit
# Run in debug mode, if set # Run in debug mode, if set
if ${debug}; then if ${debug}; then set -x ; fi
set -x
fi
# Exit on empty variable # Exit on empty variable
if ${strict}; then if ${strict}; then set -o nounset ; fi
set -o nounset
fi
# Bash will remember & return the highest exitcode in a chain of pipes. # Bash will remember & return the highest exitcode in a chain of pipes.
# This way you can catch the error in case mysqldump fails in `mysqldump |gzip`, for example. # This way you can catch the error in case mysqldump fails in `mysqldump |gzip`, for example.
set -o pipefail set -o pipefail
# Invoke the checkDependenices function to test for Bash packages
# checkDependencies
# Run your script # Run your script
mainScript mainScript
safeExit # Exit cleanly # Exit cleanly
safeExit