Last active
January 23, 2018 16:23
-
-
Save xenithorb/83a03c405bb76da992053ce9a3aebb44 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
# | |
# Usage: | |
# | |
# ./purge-file.sh <snapshot_path> "<file_or_relative_path>" | |
# | |
# Example: | |
# | |
# ./purge-file.sh /mnt/btrfs/snapshots/home "Downloads/*.iso" | |
# | |
# This will remove all *.iso files from all snapshots in /mnt/btrfs/snapshots/home.* | |
# such as a name like "home.20180121T070102-0500", it looks for | |
# /mnt/btrfs/snapshots/home.*/**/Downloads/*.iso, precisely | |
# | |
# You can also specify a file only, and the -path option to `find` will automatically | |
# remove itself | |
# | |
# | |
set -eu | |
# set -x | |
SUBVOL_PATH="$1" | |
FILE="$2" | |
DIR="${2%/*}" && [[ $FILE == "$DIR" ]] && unset DIR | |
is_ro() { | |
# Usage: is_ro <btrfs_subvolume> | |
# Exits true/false if a subvolue is read-only | |
[[ $(sudo btrfs property get "$(df -h "$1" | awk 'NR>1 { print $6 }')" ro) != 'ro=false' ]] | |
} | |
echo_wrap() { | |
echo "$*"; eval "$*" | |
} | |
is_btrfs_subvolume() { | |
local path inode fstype | |
path="$1" | |
inode=$( stat --format='%i' "$path" ) | |
fstype=$( stat -f --format='%T' "$path" ) | |
( | |
(( inode == 256 )) && [[ $fstype == "btrfs" ]] | |
) && return 0 || return 1 | |
} | |
purge_file() { | |
local file="$1" # ex: /mnt/btrfs/snapshots/home.20180121T070102-0500/file.tar.gz | |
local suffix="${file#${SUBVOL_PATH}}" # ex: .20180121T070102-0500/file.tar.gz | |
local snapshot="${SUBVOL_PATH}${suffix%%/*}" # ex: /mnt/btrfs/snapshots/home.20180121T070102-0500 | |
local was_read_only=0 | |
is_btrfs_subvolume "$snapshot" || { echo "File not in a btrfs snapshot"; exit 1; } | |
if is_ro "$snapshot"; then | |
echo_wrap sudo btrfs property set "$snapshot" ro false && | |
was_read_only=1 | |
fi | |
echo_wrap sudo rm -v -i "${file:?ERROR NO FILE}" | |
if (( was_read_only )); then | |
echo_wrap sudo btrfs property set "$snapshot" ro true | |
fi | |
} | |
# Activate/check sudo early | |
sudo -v || { echo "Needs sudo"; exit 1; } | |
# Get an array of all the files we want to remove from the snapshots | |
echo "Finding files in subvol ${SUBVOL_PATH}*..." | |
mapfile -t FILE_LIST < <( | |
sudo find "${SUBVOL_PATH}."* \ | |
-xdev ${DIR:+-path "${SUBVOL_PATH}*/**/${DIR}/\*"} \ | |
-name "${FILE##*/}" | |
) | |
echo "Done." | |
(( ${#FILE_LIST[@]} <= 0 )) && { echo "No files to delete"; exit 0; } | |
echo "Removing files.." | |
for file in "${FILE_LIST[@]}"; do | |
purge_file "$file" | |
done | |
echo "Done." |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment