Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
163 changes: 132 additions & 31 deletions scripts/maintenance/cleanup-cache.sh
Original file line number Diff line number Diff line change
@@ -1,52 +1,153 @@
#!/usr/bin/env bash

set -euo pipefail

show_help() {
cat <<'EOF'
Usage: $(basename "$0") [OPTIONS]

Clean temporary files and display cache information.
cat <<'EOF'
Usage: cleanup-cache.sh [options]

Options:
-h Show this help message
-h, --help Show this help message and exit
-n, --dry-run Show cache sizes and actions without deleting anything
-y, --yes Automatically confirm cleanup without prompting

Description:
Inspects and cleans user cache directories (thumbnail cache, trash)
and reports package manager / system journal cache usage with
recommended maintenance commands.
Never deletes critical system sockets or running process locks.
EOF
exit 0
}

if [[ "${1-}" == "-h" ]]; then
show_help
exit 0
DRY_RUN=false
AUTOYES=false

while (( "$#" )); do
case "$1" in
-h|--help)
show_help
;;
-n|--dry-run)
DRY_RUN=true
;;
-y|--yes)
AUTOYES=true
;;
-*)
echo "Error: Unknown option: $1" >&2
exit 1
;;
*)
echo "Error: Unexpected argument: $1" >&2
exit 1
;;
esac
shift
done

echo "=== Cache & Temporary Files Inspector ==="
echo ""

# 1. User thumbnail cache
THUMB_CACHE="${HOME:-}/.cache/thumbnails"
if [[ -d "$THUMB_CACHE" ]]; then
THUMB_SIZE="$(du -sh "$THUMB_CACHE" 2>/dev/null | cut -f1 || echo "0B")"
echo "User thumbnail cache: $THUMB_CACHE (Size: $THUMB_SIZE)"
if $DRY_RUN; then
echo "[DRY RUN] Would clean thumbnail files in $THUMB_CACHE"
elif $AUTOYES; then
find "$THUMB_CACHE" -type f -delete 2>/dev/null || true
echo " Cleaned thumbnail cache."
else
read -r -p "Clean user thumbnail cache? [y/N] " resp
case "$resp" in
y|Y|yes|YES)
find "$THUMB_CACHE" -type f -delete 2>/dev/null || true
echo " Cleaned thumbnail cache."
;;
*)
echo " Skipped thumbnail cache."
;;
esac
fi
else
echo "User thumbnail cache: None found."
fi

echo "Cleaning temporary files..."
# 2. User Trash
TRASH_DIR="${HOME:-}/.local/share/Trash"
if [[ -d "$TRASH_DIR" ]]; then
TRASH_SIZE="$(du -sh "$TRASH_DIR" 2>/dev/null | cut -f1 || echo "0B")"
echo "User trash: $TRASH_DIR (Size: $TRASH_SIZE)"
if $DRY_RUN; then
echo "[DRY RUN] Would empty user trash in $TRASH_DIR"
elif $AUTOYES; then
rm -rf "${TRASH_DIR:?}"/files/* "${TRASH_DIR:?}"/info/* 2>/dev/null || true
echo " Emptied user trash."
else
read -r -p "Empty user trash? [y/N] " resp
case "$resp" in
y|Y|yes|YES)
rm -rf "${TRASH_DIR:?}"/files/* "${TRASH_DIR:?}"/info/* 2>/dev/null || true
echo " Emptied user trash."
;;
*)
echo " Skipped user trash."
;;
esac
fi
fi

# 3. Systemd journal
echo ""
if command -v journalctl >/dev/null 2>&1; then
echo "Systemd Journal:"
journalctl --disk-usage 2>/dev/null || true
echo " (To vacuum logs older than 7 days: sudo journalctl --vacuum-time=7d)"
fi

if [[ -d /tmp ]]; then
find /tmp -mindepth 1 -maxdepth 1 -user "$USER" -exec rm -rf -- {} +
# 4. Package Manager Cache
echo ""
echo "Package Manager Cache Status:"
if command -v pacman >/dev/null 2>&1; then
if [[ -d /var/cache/pacman/pkg ]]; then
PAC_SIZE="$(du -sh /var/cache/pacman/pkg 2>/dev/null | cut -f1 || echo "unknown")"
echo " Pacman cache size: $PAC_SIZE (/var/cache/pacman/pkg)"
echo " Recommended: 'sudo paccache -r' or 'sudo pacman -Sc'"
fi
fi

if command -v pacman >dev/null 2>&1; then
echo
echo "Pacman cache:"
du -sh /var/cache/pacman/pkg 2>/dev/null || true
echo
echo "Use 'sudo paccache -r' to safely remove old package versions."
if command -v apt-get >/dev/null 2>&1 || command -v apt >/dev/null 2>&1; then
if [[ -d /var/cache/apt/archives ]]; then
APT_SIZE="$(du -sh /var/cache/apt/archives 2>/dev/null | cut -f1 || echo "unknown")"
echo " APT cache size: $APT_SIZE (/var/cache/apt/archives)"
echo " Recommended: 'sudo apt-get clean' or 'sudo apt-get autoclean'"
fi
fi

echo
echo "Cleanup completed."
echo "Cleaning temporary files..."
if command -v dnf >/dev/null 2>&1; then
if [[ -d /var/cache/dnf ]]; then
DNF_SIZE="$(du -sh /var/cache/dnf 2>/dev/null | cut -f1 || echo "unknown")"
echo " DNF cache size: $DNF_SIZE (/var/cache/dnf)"
echo " Recommended: 'sudo dnf clean all'"
fi
fi

if [[ -d /tmp ]]; then
find /tmp -mindepth 1 -maxdepth 1 -user "$USER" -exec rm -rf -- {} +
if command -v zypper >/dev/null 2>&1; then
if [[ -d /var/cache/zypp ]]; then
ZYPP_SIZE="$(du -sh /var/cache/zypp 2>/dev/null | cut -f1 || echo "unknown")"
echo " Zypper cache size: $ZYPP_SIZE (/var/cache/zypp)"
echo " Recommended: 'sudo zypper clean'"
fi
fi

if command -v pacman >/dev/null 2>&1; then
echo
echo "Pacman cache:"
du -sh /var/cache/pacman/pkg 2>/dev/null || true
echo
echo "Use 'sudo paccache -r' to safely remove old package versions."
if command -v apk >/dev/null 2>&1; then
if [[ -d /var/cache/apk ]]; then
APK_SIZE="$(du -sh /var/cache/apk 2>/dev/null | cut -f1 || echo "unknown")"
echo " APK cache size: $APK_SIZE (/var/cache/apk)"
echo " Recommended: 'sudo apk cache clean'"
fi
fi

echo
echo "Cleanup completed."
echo ""
echo "Cache inspection completed."
71 changes: 52 additions & 19 deletions scripts/maintenance/file-organizer.sh
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
#!/usr/bin/env bash

set -euo pipefail

show_help() {
Expand All @@ -14,9 +13,10 @@ Options:
Description:
Safely organizes unorganized loose files in a directory into subfolders
based on their file extensions (Images, Documents, Archives, Audio, Video, Code).
- Skips directories, hidden files (starting with .), and scripts.
- Safely handles filenames with spaces.
- Skips directories, symlinks, hidden files (starting with .), and files without extensions.
- Safely handles filenames with spaces, special characters, and Unicode.
- Safe dry-run mode enabled via -n / --dry-run.
- Prevents accidental execution directly on root '/' or home directory.
EOF
exit 0
}
Expand All @@ -26,14 +26,28 @@ DRY_RUN=false

while (( "$#" )); do
case "$1" in
-h|--help) show_help;;
-n|--dry-run) DRY_RUN=true;;
-h|--help)
show_help
;;
-n|--dry-run)
DRY_RUN=true
;;
-d|--dir)
shift
TARGET_DIR="${1:-.}"
if [[ -n "${2-}" && "${2-}" != -* ]]; then
TARGET_DIR="$2"
shift
else
echo "Error: Argument for $1 is missing" >&2
exit 1
fi
;;
-*)
echo "Error: Unknown option: $1" >&2
exit 1
;;
*)
TARGET_DIR="$1"
;;
-*) echo "Unknown option: $1" >&2; exit 1;;
*) TARGET_DIR="$1";;
esac
shift
done
Expand All @@ -43,7 +57,20 @@ if [[ ! -d "$TARGET_DIR" ]]; then
exit 1
fi

TARGET_DIR="$(cd "$TARGET_DIR" && pwd)"
TARGET_DIR="$(cd "$TARGET_DIR" && pwd -P)"

# Prevent accidental execution on / or $HOME directly
if [[ "$TARGET_DIR" == "/" ]]; then
echo "Error: Refusing to organize root directory '/'." >&2
exit 1
fi

if [[ -n "${HOME:-}" && "$TARGET_DIR" == "$HOME" ]]; then
echo "Error: Refusing to organize user home directory root '$HOME' directly." >&2
echo "Please specify a subfolder (e.g. ~/Downloads or ~/Desktop)." >&2
exit 1
fi

echo "=== File Organizer ==="
echo "Target directory: $TARGET_DIR"
if $DRY_RUN; then
Expand All @@ -54,20 +81,24 @@ echo ""
get_category() {
local ext="${1,,}"
case "$ext" in
jpg|jpeg|png|gif|bmp|svg|webp|tiff) echo "Images" ;;
pdf|doc|docx|txt|rtf|odt|xls|xlsx|ppt|pptx|csv) echo "Documents" ;;
zip|tar|gz|bz2|xz|7z|rar) echo "Archives" ;;
mp3|wav|ogg|flac|aac|m4a) echo "Audio" ;;
mp4|mkv|avi|mov|wmv|flv|webm) echo "Video" ;;
py|js|ts|c|cpp|h|hpp|go|rs|java|html|css|json|yaml|yml|sh) echo "Code" ;;
jpg|jpeg|png|gif|bmp|svg|webp|tiff|ico) echo "Images" ;;
pdf|doc|docx|txt|rtf|odt|xls|xlsx|ppt|pptx|csv|md) echo "Documents" ;;
zip|tar|gz|bz2|xz|7z|rar|tgz|tbz2|txz) echo "Archives" ;;
mp3|wav|ogg|flac|aac|m4a|wma) echo "Audio" ;;
mp4|mkv|avi|mov|wmv|flv|webm|m4v) echo "Video" ;;
py|js|ts|c|cpp|h|hpp|go|rs|java|html|css|json|yaml|yml|sh|bash) echo "Code" ;;
*) echo "" ;;
esac
}

moved_count=0
skipped_count=0

# Iterate over regular files in TARGET_DIR (non-recursive, ignore hidden files)
# Iterate over regular files in TARGET_DIR (non-recursive, skip symlinks and hidden files)
while IFS= read -r -d '' file; do
# Skip symlinks to avoid broken relative links or dangling targets
[[ -L "$file" ]] && continue

filename="$(basename "$file")"
# Skip hidden files
[[ "$filename" == .* ]] && continue
Expand All @@ -86,10 +117,12 @@ while IFS= read -r -d '' file; do

if $DRY_RUN; then
echo "[DRY RUN] Would move '$filename' -> '$category/'"
moved_count=$((moved_count + 1))
else
mkdir -p "$dest_dir"
if [[ -e "$dest_file" ]]; then
echo "Skipping '$filename': already exists in '$category/'"
skipped_count=$((skipped_count + 1))
else
mv -- "$file" "$dest_file"
echo "Moved '$filename' -> '$category/'"
Expand All @@ -101,7 +134,7 @@ done < <(find "$TARGET_DIR" -maxdepth 1 -type f -print0)

echo ""
if $DRY_RUN; then
echo "Dry run completed."
echo "Dry run completed. Files that would be moved: $moved_count"
else
echo "Organization complete. Files moved: $moved_count"
echo "Organization complete. Files moved: $moved_count, skipped: $skipped_count"
fi
Loading