#!/bin/sh music_dir="${XDG_MUSIC_DIR:-${HOME}/Music}" dotfiles_dir="${XDG_DOTFILES_DIR:-${HOME}/.dotfiles}" music_txt="${dotfiles_dir}/global/Music/.music.txt" music_titles="${dotfiles_dir}/global/Music/.music_titles.txt" playlist_dir="${XDG_CONFIG_HOME:-${HOME}/.config}/mpd/playlists" # Select the relative path. Sort the list so "first match" semantics in dmenu # are deterministic — otherwise filesystem order is unstable and typing a # substring (e.g. "성시경") can return whichever file find walked first. # `-not -path '*/.*'` skips hidden files (.music.txt, etc.); name filter limits to audio. selected_relpath=$(cd "$music_dir" && find . -type f -not -path '*/.*' \( -name '*.mp3' -o -name '*.m4a' -o -name '*.opus' -o -name '*.flac' -o -name '*.wav' -o -name '*.webm' \) | sed 's|^\./||' | LC_ALL=C.UTF-8 sort | dmenu -i -l 20 -p "Select a file to delete:") || exit 1 [ -n "$selected_relpath" ] || exit 1 selected_file="$music_dir/$selected_relpath" selected_filename=${selected_relpath##*/} [ -f "$selected_file" ] || { notify-send "❌ File not found: $selected_relpath" exit 1 } # Extracting YouTube video ID video_id=$(strings "$selected_file" | grep 'watch?v=' | sed 's/.*watch?v=\([a-zA-Z0-9_-]*\).*/\1/' | head -1) [ -n "$video_id" ] || { notify-send "❌ No YouTube video ID found in file: $selected_filename" exit 1 } # Confirmation dialog confirm=$(printf "Yes\nNo" | dmenu -i -p "Delete $selected_relpath and update mpc?") [ "$confirm" = "Yes" ] || { notify-send "❌ Operation cancelled." exit 0 } # Remove video_id line from .music.txt and .music_titles.txt (fixed-string match) remove_id_from() { _file="$1" [ -f "$_file" ] || return 0 _tmp="$(mktemp)" || return 1 grep -Fv "$video_id" "$_file" >"$_tmp" && mv "$_tmp" "$_file" } if remove_id_from "$music_txt" && remove_id_from "$music_titles"; then # Remove the relative path from playlists (-F avoids regex pitfalls with [], (), etc.) for playlist in "$playlist_dir"/*.m3u; do [ -e "$playlist" ] || continue if grep -Fq "$selected_relpath" "$playlist"; then grep -Fv "$selected_relpath" "$playlist" > "${playlist}.tmp" && mv "${playlist}.tmp" "$playlist" sed -i '/^$/d' "$playlist" fi done # Delete the actual music file if rm "$selected_file"; then mpc update >/dev/null notify-send " Success to delete:" "$selected_relpath" else notify-send "❌ Failed to remove file: $selected_file" fi else notify-send "❌ An error occurred." fi