Skip to content

Instantly share code, notes, and snippets.

@h8rt3rmin8r
Last active July 15, 2020 21:44
Show Gist options
  • Save h8rt3rmin8r/fe5793bb8d35bbc9e3a3ff6de83e84fa to your computer and use it in GitHub Desktop.
Save h8rt3rmin8r/fe5793bb8d35bbc9e3a3ff6de83e84fa to your computer and use it in GitHub Desktop.
Clean up the Ubuntu system screenshots from ~/Pictures
#! /usr/bin/env bash
#>------------------------------------------------------------------------------
#>
#> [ screenshot_clean.sh ]
#>
#> About:
#>
#> Clean up the Ubuntu system screenshots from ~/Pictures
#>
#> All screenshots are renamed and moved into a new directory located at
#> ~/Pictures/Screenshots. The new file names are automatically derived and
#> use the following schema:
#>
#> <UNIX_TIME>-<YYmmddHHMMSS>.png
#>
#> Consider auto-execution via cron (configurations for 'crontab -e'):
#>
#> ## Daily at midnight:
#> 0 0 * * * /usr/local/bin/screenshot_clean.sh
#>
#> ## Weekly on Monday at midnight:
#> 0 0 * * 1 /usr/local/bin/screenshot_clean.sh
#>
#> Screenshots can be similarly archived from alternative directory locations
#> in the manner described below in the "Usage" section.
#>
#> Usage:
#>
#> screenshot_clean.sh <DIRECTORY>
#> screenshot_clean.sh <OPTION>
#>
#> where "DIRECTORY" is a valid directory reference; and where "OPTION" is
#> one of the following:
#>
#> |
#> -h, --help | Print this help text to the terminal
#> |
#>
#> NOTE: No inputs are required when executing this script. If no alternative
#> directory is passed, this script will automatically execute on the files
#> found in the ~/Pictures directory.
#>
#> Attribution:
#>
#> Created on 20200715 by h8rt3rmin8r ([email protected])
#>
#> Source:
#>
#> https://pastebin.com/YAUbYGFd
#> https://gist.github.com/h8rt3rmin8r/fe5793bb8d35bbc9e3a3ff6de83e84fa
#>
#>------------------------------------------------------------------------------
# Declare functions
function sc_datemod() {
# Date transformation function (date stamp into UNIX timestamp conversion)
local i_all="$@"
local out_len=10
if [[ "${#i_all}" -lt 8 || "${i_all}" =~ [^0-9] ]]; then
return 1
fi
local i_all_a=${i_all:0:8}
local i_all_b=${i_all#$i_all_a}
case "$(printf '%s' ${i_all_b} | wc -c)" in
1|3|5)
return 1
;;
0)
local i_time="00:00:00"
;;
2)
local i_time="${i_all_b}:00:00"
;;
4)
local i_time="${i_all_b:0:2}:${i_all_b: -2}:00"
;;
6)
local i_hour=${i_all_b:0:2}
local i_minute_pre=${i_all_b#$i_hour}
local i_minute=${i_minute_pre:0:2}
local i_second=${i_all_b: -2}
local i_time="${i_hour}:${i_minute}:${i_second}"
;;
7|8|9|10|11|12|13|14|15|16|17|18|19|20)
local i_hour=${i_all_b:0:2}
local i_minute_pre=${i_all_b:0:4}
local i_minute=${i_minute_pre: -2}
local i_second_pre=${i_all_b:0:6}
local i_second="${i_second_pre: -2}.${i_all_b:6}"
local i_time="${i_hour}:${i_minute}:${i_second}"
;;
esac
local i_year=${i_all_a:0:4}
local i_month_pre=${i_all_a:0:6}
local i_month=${i_month_pre: -2}
local i_day=${i_all_a: -2}
local in_x="${i_year}-${i_month}-${i_day} ${i_time}"
local output_prime=$(date -d "${in_x}" '+%s%N' 2>/dev/null)
local e_c=$(date -d "${in_x}" '+%s%N' &>/dev/null; echo "$?")
local output=${output_prime:0:$out_len}
echo "${output}"
return ${e_c}
}
function sc_help() {
# Script help text printing function
cat "${0}" \
| grep -E '^#[>]' \
| sed 's/^..//'
return $?
}
function sc_l2a() {
# File-lines-to-array conversion function
if [[ -t 0 ]]; then
if [[ "x${1}" == "x" ]]; then
return 1
fi
if [[ -f "${1}" ]]; then
mapfile -t L_ARR <"${1}"
else
return 1
fi
else
return 1
fi
export L_ARR
return $?
}
function sc_ls() {
# Screenshot file listing function
ls -CF "${t_d}" \
| tr '\t' '\n' \
| sed 's/\ \{2\}/\n/g' \
| sed '/^[ ]*$/d' \
| sed 's/^\ *//' \
| sed 's/[*@]$//' \
| sed '/[/]/d' \
| LC_ALL=C sort \
| grep -E '^S([cehnorst]){9}.from.([12][0-9][0-9][0-9])-(0[1-9]|1[0-2])-(0[1-9]|1[0-9]|2[0-9]|3[0-1]) (0[0-9]|1[0-9]|2[0-3])-([0-5][0-9])-([0-5][0-9])\.png'
return $?
}
function sc_vb() {
# Script verbosity printing function
local runtime=$(date '+%s%N')
local sh_name="${s_h}"
local i_n="$@"
echo "${runtime}|${sh_name}|${i_n}" &>/dev/stderr
return $?
}
# Declare variables and arrays, then execute operations
_q1=$'\u0027'
_q2=$'\u0022'
_pa=$'\u0028'
_pb=$'\u0029'
_sp=$'\u0020'
_usd=$'\u0024'
s_h_pre="${0//*\/}"
s_h="${s_h_pre%[.]sh}"
r_t="$(date '+%s%N')"
n_c="${RANDOM:0:1}${RANDOM: -1}${RANDOM: -1}${RANDOM: -1}${RANDOM: -1}"
t_h="${HOME}"
t_d="${t_h}/Pictures"
o_d="${t_d}/Screenshots"
tmpf="/tmp/${s_h}_${r_t}-${n_c}"
declare -a sc_source=()
declare -a sc_outmod=()
declare -a sc_output=()
## Catch help text requests
if [[ "${1}" == "-h" || "${1}" =~ ^[-]+help$ ]]; then
sc_help
exit $?
fi
## Catch alternative target directory references
if [[ ! "x${1}" == "x" ]]; then
if [[ -d "${1}" ]]; then
t_d=$(readlink -f "${1}")
else
sc_vb "ERROR: Input is not a valid directory reference: ${1}"
sc_vb "Use '--help' for more information"
exit 1
fi
fi
## Make the temp file
touch "${tmpf}"
## Store a list of valid screenshot images in the temp file
sc_ls >> "${tmpf}"
## Consume the lines of the temp file into an array, "L_ARR"
sc_l2a "${tmpf}"
## Kill the script if the "L_ARR" array has no elements
if [[ "${#L_ARR[@]}" -lt 1 ]]; then
sc_vb "ERROR: No valid screenshots were found"
rm "${tmpf}" &>/dev/null
unset L_ARR
unset sc_source
unset sc_outmod
unset sc_output
unset sc_sequence
exit 1
fi
## Loop through the discovered screenshot file names and generate three arrays
##
## 1) sc_source ==> same as "L_ARR"
## 2) sc_output ==> second half of the pending output file names
## 3) sc_outmod ==> date strings to be transformed in the following loop
##
for i in "${L_ARR[@]}"; do
sc_vb "Processing: ${i}"
ca_src="${i}"
ca_out=$(sed 's/^.*from\ //' <<<"${ca_src}" | tr -d ' ' | tr -d '-')
ca_mod=$(cut -d '.' -f1 <<<"${ca_out}")
sc_source+=( "${ca_src}" )
sc_output+=( "${ca_out}" )
sc_outmod+=( "${ca_mod}" )
done
## Set variables and arrays required by the second loop processes
sc_count="${#sc_source[@]}"
let sc_count=sc_count-1
declare -a sc_sequence=( $(seq 0 1 ${sc_count}) )
## Clear out the temp file so it can be used as a parallel command file
echo -n > "${tmpf}"
for i in "${sc_sequence[@]}"; do
## Derive the parallel commands
cb_src="${sc_source[$i]}"
cb_mod_pre="${sc_outmod[$i]}"
cb_mod=$(sc_datemod "${cb_mod_pre}")
cb_out="${sc_output[$i]}"
cb_a="${t_d}/${cb_src}"
cb_b="${o_d}/${cb_mod}-${cb_out}"
str_a="mv ${_q2}${cb_a}${_q2} ${_q2}${cb_b}${_q2};"
str_b_a="echo ${_q2}${_usd}${_pa}date ${_q1}+%s%N${_q1}${_pb}"
str_b_b="|${s_h}|Complete: ${cb_a} ==> ${cb_b}${_q2}"
str_b="${str_b_a}${str_b_b}"
## Write the parallel commands into the temp file
echo "${str_a} ${str_b}" >> "${tmpf}"
done
## Make sure the output directory exists
mkdir -p "${o_d}"
## Perform the file moving and renaming process using GNU Parallel
parallel --no-notice -k :::: "${tmpf}" 2>/dev/null
## Capture the exit code from the moving processes
e_c="$?"
##
## If the exit code was bad, inform the user that parallel should be installed
## if parallel cannot be found on the system; otherwise let the user know that
## something went wrong
##
if [[ "${e_c}" -ne 0 ]]; then
sc_vb "ERROR: Missing required software 'parallel'"
sc_vb "Install 'parallel' with: 'sudo apt-get install parallel' and try again"
fi
## Clean up the workspace (destroy the temp file and unset all arrays)
rm "${tmpf}" &>/dev/null
unset L_ARR
unset sc_source
unset sc_outmod
unset sc_output
unset sc_sequence
exit ${e_c}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment