clipdel (2584B)
1#!/usr/bin/env bash 2 3CM_REAL_DELETE=0 4if [[ $1 == -d ]]; then 5 CM_REAL_DELETE=1 6 shift 7fi 8 9shopt -s nullglob 10 11cache_dir=$(clipctl cache-dir) 12cache_file=$cache_dir/line_cache 13lock_file=$cache_dir/lock 14lock_timeout=2 15 16if [[ $1 == --help ]] || [[ $1 == -h ]]; then 17 cat << 'EOF' 18clipdel deletes clipmenu entries matching a regex. By default, just lists what 19it would delete, pass -d to do it for real. If no pattern is passed as an argument, 20it will try to read one from standard input. 21 22".*" is special, it will just nuke the entire data directory, including the 23line caches and all other state. 24 25Arguments: 26 27 -d Delete for real. 28 29Environment variables: 30 31- $CM_DIR: specify the base directory to store the cache dir in (default: $XDG_RUNTIME_DIR, $TMPDIR, or /tmp) 32EOF 33 exit 0 34fi 35 36if ! [[ -f $cache_file ]]; then 37 printf '%s\n' "No line cache file found, no clips exist" >&2 38 exit 0 # Well, this is a kind of success... 39fi 40 41if [[ -n $1 ]]; then 42 raw_pattern=$1 43elif ! [[ -t 0 ]]; then 44 IFS= read -r raw_pattern 45fi 46 47esc_pattern=${raw_pattern//\#/'\#'} 48 49# We use 2 separate sed commands so "esc_pattern" matches only the 'clip' text 50# without the timestamp (e.g. $> clipdel '^delete_exact_match$') 51sed_common_command="s#^[0-9]\+ ##;\\#${esc_pattern}#" 52 53if ! [[ $raw_pattern ]]; then 54 printf '%s\n' 'No pattern provided, see --help' >&2 55 exit 2 56elif [[ "$raw_pattern" == ".*" ]]; then 57 delete_cache_dir=1 58else 59 mapfile -t matches < <( 60 sed -n "${sed_common_command}p" "$cache_file" | 61 sort -u 62 ) 63fi 64 65exec {lock_fd}> "$lock_file" 66 67if (( CM_REAL_DELETE )); then 68 if (( delete_cache_dir )); then 69 flock -x -w "$lock_timeout" "$lock_fd" || exit 70 rm -rf -- "$cache_dir" 71 mkdir -p -- "$cache_dir" 72 exit 0 73 else 74 flock -x -w "$lock_timeout" "$lock_fd" || exit 75 76 for match in "${matches[@]}"; do 77 ck=$(cksum <<< "$match") 78 rm -f -- "$cache_dir/$ck" 79 done 80 81 temp=$(mktemp) 82 # sed 'h' and 'g' here means save and restore the line, so 83 # timestamps are not removed from non-deleted lines. 'd' deletes the 84 # line and restarts, skipping 'g'/restore. 85 # https://www.gnu.org/software/sed/manual/html_node/Other-Commands.html#Other-Commands 86 sed "h;${sed_common_command}d;g" "$cache_file" > "$temp" 87 mv -- "$temp" "$cache_file" 88 89 flock -u "$lock_fd" 90 fi 91elif (( delete_cache_dir )); then 92 printf 'delete cache dir: %s\n' "$cache_dir" 93elif (( ${#matches[@]} )); then 94 printf '%s\n' "${matches[@]}" 95fi