Skip to content

Instantly share code, notes, and snippets.

@kwhitefoot
Last active January 16, 2022 13:52
Show Gist options
  • Save kwhitefoot/ee6c44f6c4a58d77523c599906267f36 to your computer and use it in GitHub Desktop.
Save kwhitefoot/ee6c44f6c4a58d77523c599906267f36 to your computer and use it in GitHub Desktop.
Nautlis script to move selected files to an archive directory
#!/bin/bash
set -e # exit immediately on failure
set -u # fail if unset variable is used
set -o pipefail # exit with first error in a pipeline
set -x
#####################
# Move the specified files to the archive
# This version has no error handling, it is a proof of concept that
# will be developed further if necessary
# Does not move directories or their contents only individual files.
# Does not move symlinks.
# Depends on:
# - zenity: to display error and information messages
# Configuration:
# Expects a configuration file named "move to archive.config" in the
# same directory as the script.
# Logging:
# Creates a log in "move to archive.log". The script reduces this
# file to the last 1000 lines before adding more.
#####################
show_info(){
echo "${1}"
zenity --info --width=400 \
--title="${title}" \
--text="${1}"
}
limit_log(){
local log
log="$(tail --lines=${MAX_LOG_FILE_LINES} "${log_file}")" &&
echo "${log}" > "${log_file}"
}
abs_filename() {
# $1 : relative filename
echo "$(cd "$(dirname "$1")" && pwd)/$(basename "$1")"
}
iso_date_time(){
date --iso-8601="seconds"
}
archive_one(){
local -r src="${1}"
local -r dst="${ARCHIVE}/${src}"
local -r timestamp="$(iso_date_time)"
local -r version="${dst}.${timestamp}"
echo "----------------"
echo "src: $src"
echo "dst: $dst"
# Move the file to the archive
mv --verbose "${src}" "${dst}"
# Link the file to a dated version in case the user creates or
# restores the file and archives it again.
ln --verbose "${dst}" "${version}"
# # Leave a marker in place of the source to remind the user that
# # the archived file exists.
# local -r placeholder="${src}.archived"
# echo "archive=\"${dst}\"" > "${placeholder}"
# echo "when=\"${timestamp}\"" >> "${placeholder}"
# replace the source file with a symlink
ln --symbolic --verbose "${dst}" "${src}"
}
archive_all(){
local -i count=0
local -i total="${#}"
local -i progress_percent
for i in "${@}"
do
(( ++count ))
echo "item: $i"
local src="$(abs_filename "${i}")"
if [[ -d "${src}" ]]
then
local msg="Cannot archive directories (yet)\n ${src}"
echo "${msg}"
(( ++count_directories ))
continue
fi
if [[ -L "${src}" ]]
then
local msg="Ignoringing symlink\n ${src}"
echo "${msg}"
(( ++count_symlinks ))
continue
fi
archive_one "${src}"
# Note pre-increment to avoid killing the script.
(( ++count_archived ))
(( progress_percent = count * 100 / total ))
echo "${progress_percent}" >&"${progress[1]}"
done
echo "100" >&"${progress[1]}"
echo "----------------"
echo "Archived ${count_archived} files"
}
# Wrap the main in a block so that we can redirect to a log file.
# Redirect errors as well
main(){
# Load the configuration. At the moment this is just the path to
# the archive.
# The configuration file should look somthing like this
# #!/bin/bash
# ARCHIVE="/media/username/diskname/path/to/archive/"
# MAX_LOG_FILE_LINES=1000
# shellcheck source=archive.config
. "${script_path}.config"
declare -rg title="$script_name"
# Create a coprocess to show the progress
coproc progress ( zenity --progress --auto-close --title="${title}" )
echo "The progress coprocess array: ${progress[@]}"
echo "The PID of the print coprocess is ${progress_PID}"
echo
echo
echo "================"
date
echo "Archiving to ${ARCHIVE}"
echo "Current directory"
pwd
echo "Item count: ${#}"
declare -ig count_archived=0
declare -ig count_symlinks=0
declare -ig count_directories=0
if [[ ${#} == 0 ]]
then
local -r msg="No files selected."
show_info "${msg}"
else
archive_all "${@}"
fi
local -r exit_msg="Archived ${count_archived} of ${#} files, \n\
ignored ${count_directories} directories, \n\
ignored ${count_symlinks} symlinks."
show_info "${exit_msg}"
echo "================"
echo
echo
}
# Defaults:
declare -i MAX_LOG_FILE_LINES=1000
declare -r script_name="$(basename "$0")"
declare -r script_path="$(readlink -f "$0")"
declare -r log_file="${script_path}.log"
limit_log
main "${@}" &>> "${log_file}"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment