Skip to content

Instantly share code, notes, and snippets.

@theagoliveira
Last active March 13, 2025 05:54
Show Gist options
  • Save theagoliveira/70b477f3c8d908c9d76e815940c196c3 to your computer and use it in GitHub Desktop.
Save theagoliveira/70b477f3c8d908c9d76e815940c196c3 to your computer and use it in GitHub Desktop.
Script to backup files between drives using rsync and list them using tree
*.txt
*.tar.gz
#!/bin/bash
#
# Author: Thiago Cavalcante
# github.com/theagoliveira
SCRIPTPATH="$( cd "$(dirname "$0")" || exit ; pwd -P )"
script_configs_folder="backup-and-list-configs"
full_script_configs_folder="$SCRIPTPATH/$script_configs_folder"
list_flag=false
dry_run=false
from_flag=false
to_flag=false
inc_flag=false
exc_flag=false
while getopts ":f:t:nli:e:" opt; do
case ${opt} in
f ) # FROM
from=$OPTARG
from_flag=true
;;
t ) # TO
to=$OPTARG
to_flag=true
tmp=${to%"${to##*[!/]}"}
to_base=${tmp##*/}
;;
n ) # DRY-RUN
dry_run=true
;;
l ) # LIST
list_flag=true
;;
i ) # INCLUDE
inc=$OPTARG
inc_flag=true
;;
e ) # TO
exc=$OPTARG
exc_flag=true
;;
\? )
echo "Unsupported option."
echo "Usage: -f FROM_DIR -t TO_DIR [-n -l] { -i INCLUDE_LIST | -e EXCLUDE_LIST }"
exit 0
;;
: )
echo "You have to specify an directory/list."
exit 0
esac
done
if [ $from_flag = false ] || [ $to_flag = false ]
then
echo "You have to specify both directories."
exit 0
fi
if ! [ -d "$from" ] || ! [ -d "$to" ]
then
echo "You have to specify valid directories."
exit 0
fi
if [[ $inc_flag = false && $exc_flag = false ]] || \
[[ $inc_flag = true && $exc_flag = true ]]
then
echo "You have to specify either an include list or an exclude list."
exit 0
fi
if [ $exc_flag = true ] && ! [ -f "$full_script_configs_folder/$exc" ]
then
echo "You have to specify a valid exclude list."
exit 0
fi
if [ $inc_flag = true ] && ! [ -f "$full_script_configs_folder/$inc" ]
then
echo "You have to specify a valid include list."
exit 0
fi
if [ $dry_run = false ]
then
echo
echo "##################"
echo "# BACKUP"
echo "##################"
echo
else
echo
echo "##################"
echo "# BACKUP DRY-RUN"
echo "##################"
echo
fi
today=$(date +%Y-%m-%d)
start_time_total=$(date +%s)
file_trees_folder="File Trees"
for f in "$to"/*;
do
if [ $exc_flag = true ]
then
if grep -Fxq "${f##*/}" "$full_script_configs_folder/$exc"
then
echo "##################"
echo "# EXCLUDED FOLDER: $f"
echo "##################"
else
echo "##################"
echo "# FOLDER: $f"
echo "##################"
start_time=$(date +%s)
cd "$f" || exit
current=${PWD##*/}
if [ $dry_run = false ]
then
rsync -a -h -v --progress --delete -i -s "$from/$current" "$to"
else
rsync -a -h -v --progress --delete -i -s -n "$from/$current" "$to"
fi
end_time=$(date +%s)
echo "Execution time: $((end_time - start_time)) seconds"
fi
fi
if [ $inc_flag = true ]
then
if grep -Fxq "${f##*/}" "$full_script_configs_folder/$inc"
then
echo "##################"
echo "# FOLDER: $f"
echo "##################"
start_time=$(date +%s)
cd "$f" || exit
current=${PWD##*/}
exception_file="$full_script_configs_folder/${current}_exception_${to_base}.txt"
if [ $dry_run = false ]
then
if [ -f "$exception_file" ]
then
echo "##################"
echo "# EXCEPTION"
echo "# $(cat "$exception_file")"
echo "##################"
rsync -a -h -v --progress --delete -i -s --exclude-from "$exception_file" "$from/$current" "$to"
else
rsync -a -h -v --progress --delete -i -s "$from/$current" "$to"
fi
else
if [ -f "$exception_file" ]
then
echo "##################"
echo "# EXCEPTION"
cat "$exception_file"
echo "##################"
rsync -a -h -v --progress --delete -i -s -n --exclude-from "$exception_file" "$from/$current" "$to"
else
rsync -a -h -v --progress --delete -i -s -n "$from/$current" "$to"
fi
fi
end_time=$(date +%s)
echo "Execution time: $((end_time - start_time)) seconds"
else
echo "##################"
echo "# EXCLUDED FOLDER: $f"
echo "##################"
fi
fi
done;
if [ $dry_run = false ] && [ $list_flag = true ]
then
echo
echo "##################"
echo "# LIST"
echo "##################"
echo
echo "Removing old lists folders (PC and HDD)"
rm -r "${to:?}/${file_trees_folder:?}/"
rm -r "${from:?}/${file_trees_folder:?}/"
echo "Creating new lists folder (PC)"
mkdir "$to/$file_trees_folder/"
for f in "$to"/*;
do
[ -d "$f" ]
if [ "$f" != "$to/\$RECYCLE.BIN" ] && \
[ "$f" != "$to/.Trash-1000" ] && \
[ "$f" != "$to/System Volume Information" ] && \
[ "$f" != "$to/$file_trees_folder" ]
then
echo FOLDER: "$f"
start_time=$(date +%s)
cd "$f" || exit
current=${PWD##*/}
tree -asDvn -o "$to/$file_trees_folder/$current $today.txt"
end_time=$(date +%s)
echo "Created $to/$file_trees_folder/$current $today.txt"
echo "Execution time: $((end_time - start_time)) seconds"
fi
done;
echo "Copying new lists to HDD"
cp -r "$to/$file_trees_folder/" "$from/"
fi
end_time_total=$(date +%s)
echo "TOTAL EXECUTION TIME: $((end_time_total - start_time_total)) SECONDS"
#!/usr/bin/env bash
cd "$CODE/gists/backup-and-list" || exit
if [ -n "$1" ]; then
name="$1"
else
name=$(uname -rn | sed -r -e "s/ /\--/g")
fi
echo "name: $name"
rm "exported/keyboard-shortcuts--${name}.tar.gz"
rm "exported/mimeapps-list--${name}.tar.gz"
rm "exported/configs--${name}.tar.gz"
rm "exported/dolphin-configs--${name}.tar.gz"
rm "exported/skins--${name}.tar.gz"
shopt -s globstar
echo
printf "CONFIGURATIONS BACKUP\n"
collect_files() {
local files=()
for n in "$@"; do
# Handle glob patterns
if [[ "$n" == *"*"* ]]; then
# Expand the glob pattern and add matching files to the array
for match in $n; do
if [[ -f "$match" ]]; then
files+=("$match")
fi
done
else
# Add the file directly if it exists
if [[ -f "$n" ]]; then
files+=("$n")
fi
fi
done
# Print the filenames with proper quoting
printf '%q ' "${files[@]}"
}
echo
echo "keyboard-shortcuts"
files=$(
collect_files \
"$HOME/.config/kdeglobals" \
"$HOME/.config/kglobalshortcutsrc" \
"$HOME/.config/khotkeysrc" \
"$HOME/.config/kwinrc" \
"$HOME/.config/plasma-org.kde.plasma.desktop-appletsrc" \
"$HOME/.local/share/kxmlgui5/katepart/katepart5ui.rc" \
"$HOME/.local/share/kxmlgui5/konsole/konsoleui.rc" \
"$HOME/.local/share/kxmlgui5/konsole/sessionui.rc" \
"$HOME/.local/share/kxmlgui5/kwrite/kwriteui.rc"
)
eval "tar czf exported/keyboard-shortcuts--${name}.tar.gz ${files}"
echo
echo "mimeapps-list"
files=$(
collect_files \
"$HOME/.config/kde-mimeapps.cache" \
"$HOME/.config/kde-mimeapps.desktop" \
"$HOME/.config/kde-mimeapps.list" \
"$HOME/.config/kde-mimeinfo.cache" \
"$HOME/.config/kde-mimeinfo.desktop" \
"$HOME/.config/kde-mimeinfo.list" \
"$HOME/.config/kde-vscode-reuse-window.cache" \
"$HOME/.config/kde-vscode-reuse-window.desktop" \
"$HOME/.config/kde-vscode-reuse-window.list" \
"$HOME/.config/mimeapps.cache" \
"$HOME/.config/mimeapps.desktop" \
"$HOME/.config/mimeapps.list" \
"$HOME/.config/mimeinfo.cache" \
"$HOME/.config/mimeinfo.desktop" \
"$HOME/.config/mimeinfo.list" \
"$HOME/.config/vscode-reuse-window.cache" \
"$HOME/.config/vscode-reuse-window.desktop" \
"$HOME/.config/vscode-reuse-window.list" \
"$HOME/.local/share/applications/kde-mimeapps.cache" \
"$HOME/.local/share/applications/kde-mimeapps.desktop" \
"$HOME/.local/share/applications/kde-mimeapps.list" \
"$HOME/.local/share/applications/kde-mimeinfo.cache" \
"$HOME/.local/share/applications/kde-mimeinfo.desktop" \
"$HOME/.local/share/applications/kde-mimeinfo.list" \
"$HOME/.local/share/applications/kde-vscode-reuse-window.cache" \
"$HOME/.local/share/applications/kde-vscode-reuse-window.desktop" \
"$HOME/.local/share/applications/kde-vscode-reuse-window.list" \
"$HOME/.local/share/applications/mimeapps.cache" \
"$HOME/.local/share/applications/mimeapps.desktop" \
"$HOME/.local/share/applications/mimeapps.list" \
"$HOME/.local/share/applications/mimeinfo.cache" \
"$HOME/.local/share/applications/mimeinfo.desktop" \
"$HOME/.local/share/applications/mimeinfo.list" \
"$HOME/.local/share/applications/vscode-reuse-window.cache" \
"$HOME/.local/share/applications/vscode-reuse-window.desktop" \
"$HOME/.local/share/applications/vscode-reuse-window.list" \
"/etc/xdg/kde-mimeapps.cache" \
"/etc/xdg/kde-mimeapps.desktop" \
"/etc/xdg/kde-mimeapps.list" \
"/etc/xdg/kde-mimeinfo.cache" \
"/etc/xdg/kde-mimeinfo.desktop" \
"/etc/xdg/kde-mimeinfo.list" \
"/etc/xdg/kde-vscode-reuse-window.cache" \
"/etc/xdg/kde-vscode-reuse-window.desktop" \
"/etc/xdg/kde-vscode-reuse-window.list" \
"/etc/xdg/mimeapps.cache" \
"/etc/xdg/mimeapps.desktop" \
"/etc/xdg/mimeapps.list" \
"/etc/xdg/mimeinfo.cache" \
"/etc/xdg/mimeinfo.desktop" \
"/etc/xdg/mimeinfo.list" \
"/etc/xdg/vscode-reuse-window.cache" \
"/etc/xdg/vscode-reuse-window.desktop" \
"/etc/xdg/vscode-reuse-window.list" \
"/usr/local/share/applications/kde-mimeapps.cache" \
"/usr/local/share/applications/kde-mimeapps.desktop" \
"/usr/local/share/applications/kde-mimeapps.list" \
"/usr/local/share/applications/kde-mimeinfo.cache" \
"/usr/local/share/applications/kde-mimeinfo.desktop" \
"/usr/local/share/applications/kde-mimeinfo.list" \
"/usr/local/share/applications/kde-vscode-reuse-window.cache" \
"/usr/local/share/applications/kde-vscode-reuse-window.desktop" \
"/usr/local/share/applications/kde-vscode-reuse-window.list" \
"/usr/local/share/applications/mimeapps.cache" \
"/usr/local/share/applications/mimeapps.desktop" \
"/usr/local/share/applications/mimeapps.list" \
"/usr/local/share/applications/mimeinfo.cache" \
"/usr/local/share/applications/mimeinfo.desktop" \
"/usr/local/share/applications/mimeinfo.list" \
"/usr/local/share/applications/vscode-reuse-window.cache" \
"/usr/local/share/applications/vscode-reuse-window.desktop" \
"/usr/local/share/applications/vscode-reuse-window.list" \
"/usr/share/applications/kde-mimeapps.cache" \
"/usr/share/applications/kde-mimeapps.desktop" \
"/usr/share/applications/kde-mimeapps.list" \
"/usr/share/applications/kde-mimeinfo.cache" \
"/usr/share/applications/kde-mimeinfo.desktop" \
"/usr/share/applications/kde-mimeinfo.list" \
"/usr/share/applications/kde-vscode-reuse-window.cache" \
"/usr/share/applications/kde-vscode-reuse-window.desktop" \
"/usr/share/applications/kde-vscode-reuse-window.list" \
"/usr/share/applications/mimeapps.cache" \
"/usr/share/applications/mimeapps.desktop" \
"/usr/share/applications/mimeapps.list" \
"/usr/share/applications/mimeinfo.cache" \
"/usr/share/applications/mimeinfo.desktop" \
"/usr/share/applications/mimeinfo.list" \
"/usr/share/applications/vscode-reuse-window.cache" \
"/usr/share/applications/vscode-reuse-window.desktop" \
"/usr/share/applications/vscode-reuse-window.list"
)
eval "tar czf exported/mimeapps-list--${name}.tar.gz ${files}"
echo
echo "configs"
files=$(
collect_files \
"$HOME/.alacritty.yml" \
"$HOME/.bash_history" \
"$HOME/.bash_profile" \
"$HOME/.bashrc" \
"$HOME/.config/atuin/config.toml" \
"$HOME/.config/atuin/server.toml" \
"$HOME/.config/Code/User/keybindings.json" \
"$HOME/.config/Code/User/settings.json" \
"$HOME/.config/Code/User/snippets/"*.json \
"$HOME/.config/mps-youtube/config" \
"$HOME/.config/mpv/input.conf" \
"$HOME/.config/mpv/mpv.conf" \
"$HOME/.config/plasmarc" \
"$HOME/.config/spotifyd/spotifyd.conf" \
"$HOME/.config/sublime-text-3/Packages/User/SyncSettings.sublime-settings" \
"$HOME/.config/sublime-text/Packages/User/"*.sublime-keymap \
"$HOME/.config/sublime-text/Packages/User/"*.sublime-settings \
"$HOME/.config/terminator/config" \
"$HOME/.config/yakuakerc" \
"$HOME/.config/yay/config.json" \
"$HOME/.gitconfig" \
"$HOME/.local/share/atuin/history.db" \
"$HOME/.local/share/atuin/key" \
"$HOME/.local/share/atuin/session" \
"$HOME/.local/share/konsole/default.dark.colorscheme" \
"$HOME/.local/share/konsole/Dracula.colorscheme" \
"$HOME/.local/share/konsole/Shell.profile" \
"$HOME/.oh-my-zsh/plugins/web-search/web-search.plugin.zsh" \
"$HOME/.p10k.zsh" \
"$HOME/.profile" \
"$HOME/.pythonrc" \
"$HOME/.ssh/config" \
"$HOME/.ticker.yaml" \
"$HOME/.zprofile" \
"$HOME/.zsh_history" \
"$HOME/.zshenv" \
"$HOME/.zshrc" \
"/etc/default/grub" \
"/etc/fstab" \
"/etc/pacman.conf"
)
eval "tar czf exported/configs--${name}.tar.gz ${files}"
echo
echo "dolphin-configs"
files=$(
collect_files \
"$HOME/.config/dolphinrc" \
"$HOME/.local/share/kxmlgui5/dolphin/dolphinui.rc" \
"$HOME/.local/share/user-places.xbel"
)
eval "tar czf exported/dolphin-configs--${name}.tar.gz ${files}"
echo
echo "skins"
files=$(
collect_files \
"$HOME/.local/share/plasma/desktoptheme/ChromeOS/"**/* \
"$HOME/.local/share/yakuake/kns_skins/monochrome/"**/*
)
eval "tar czf exported/skins--${name}.tar.gz ${files}"
shopt -u globstar
#!/usr/bin/env bash
## SOURCE: https://github.com/dylanaraps/pure-bash-bible#get-the-base-name-of-a-file-path
basename() {
# Usage: basename "path" ["suffix"]
local tmp
tmp=${1%"${1##*[!/]}"}
tmp=${tmp##*/}
tmp=${tmp%"${2/"$tmp"}"}
printf '%s\n' "${tmp:-/}"
}
printf "BOOKMARKS BACKUP\n\n"
rm -rf "$BOOKMARKS"/md/*.md
rm -rf "$BOOKMARKS"/html/*.html
rm -rf "$BOOKMARKS"/json/*.json
rm -rf "$BOOKMARKS"/all/*.*
printf -v DATE '%(%Y%m%d)T' '-1'
counter=0
echo "[" > "$BOOKMARKS"/all/all_bookmarks_temp.json
for bm in "$BOOKMARKS"/*.db
do
if [ $counter != 0 ]; then
echo "," >> "$BOOKMARKS"/all/all_bookmarks_temp.json
fi
BASENAME=$(basename "$bm" ".db")
buku --db "$bm" -e "$BOOKMARKS"/md/"$BASENAME"_"$DATE".md > /dev/null 2>&1
EXPORTED=$(buku --db "$bm" -e "$BOOKMARKS"/html/"$BASENAME"_"$DATE".html)
buku --db "$bm" -p -j > "$BOOKMARKS"/json/"$BASENAME"_"$DATE".json
buku --db "$bm" -p -j | sed -r -e 's/^(\[|\])$//g' >> "$BOOKMARKS"/all/all_bookmarks_temp.json
counter+=1
printf "%-25s %12s\n" "$BASENAME" "$EXPORTED"
done
echo
echo "]" >> "$BOOKMARKS"/all/all_bookmarks_temp.json
jq . "$BOOKMARKS"/all/all_bookmarks_temp.json > "$BOOKMARKS"/all/all_bookmarks_"$DATE".json
rm -rf "$BOOKMARKS"/all/all_bookmarks_temp.json
cat "$BOOKMARKS"/md/*.md > "$BOOKMARKS"/all/all_bookmarks_"$DATE".md
buku --db "$BOOKMARKS/default_urls.db" -p --nc | /usr/bin/grep -P -i '(http.*)' | sed 's/ > //g' > "$CODE/gists/backup-and-list/default_urls.txt"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment