jfjfjjfjfjjf
#!/bin/bash # Name: audio7z.sh # Creates audio7z.db with EXACT paths from 7z archives
echo “Creating audio7z.db database…” echo “========================================”
Check if audio.db exists
if [ ! -f “audio.db” ]; then echo “Error: audio.db not found!” exit 1 fi
Create new database
if [ -f “audio7z.db” ]; then read -p “audio7z.db exists. Overwrite? [y/N]:” -n 1 -r echo “” if [[ ! \(REPLY =~ ^[Yy]\) ]]; then exit 0 fi rm -f audio7z.db fi
Create table
echo “Creating table structure…” sqlite3 audio7z.db <<EOF CREATE TABLE audio_files ( id INTEGER PRIMARY KEY, path TEXT NOT NULL, filename TEXT NOT NULL, directory TEXT NOT NULL, title TEXT, artist TEXT, album TEXT, year INTEGER, track INTEGER, genre TEXT, duration INTEGER, size INTEGER, bitrate INTEGER, sample_rate INTEGER, channels INTEGER, codec TEXT, file_type TEXT, last_modified INTEGER, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ); EOF
Copy existing data
echo “Copying from audio.db…” sqlite3 audio.db “.dump audio_files” | grep -E “^INSERT” | sqlite3 audio7z.db
EXISTING_COUNT=$(sqlite3 audio7z.db “SELECT COUNT(*) FROM audio_files”) echo “Copied $EXISTING_COUNT files.”
Scan 7z archives
echo “” echo “Scanning .7z archives in /storage/5C6E-0E7C…” echo “This may take a while…” echo “”
ARCHIVE_COUNT=0 TOTAL_ADDED=0
Temp directory
TEMP_DIR=$(mktemp -d)
Find all .7z files
find /storage/5C6E-0E7C -type f -name “*.7z” | while read -r archive; do ((ARCHIVE_COUNT++)) echo “[$ARCHIVE_COUNT] Processing: \((basename "\)archive”)”
# List ALL files in archive first to see structure
7z l "$archive" 2>/dev/null | while read -r line; do
# Check if it's an audio file
if echo "$line" | grep -qiE "\.(opus|ogg|flac|wav|m4a|oga|mka|mp3|aac|wma)$"; then
# Get the FULL path from the line - CRITICAL FIX
# The path is the LAST field, but we need to preserve spaces and special chars
# Use awk with a space delimiter and print from field 6 to end
full_path=$(echo "$line" | awk '{for(i=6;i<=NF;i++) printf "%s%s", (i==6?"":" "), $i}')
# Clean any carriage returns
full_path=$(echo "$full_path" | tr -d '\r' | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')
if [ -z "$full_path" ] || [[ "$full_path" == */ ]]; then
continue
fi
# Store with EXACT mpv syntax that works
# Database stores: archive:///path\|/internal/full/path
archive_path_stored="archive://$archive\\|/$full_path"
filename=$(basename "$full_path")
# Get size (field 4)
size=$(echo "$line" | awk '{print $4}')
if [ "$size" = "----" ] || ! [[ "$size" =~ ^[0-9]+$ ]]; then
size=0
fi
# File type
extension="${filename##*.}"
file_type=$(echo "$extension" | tr '[:lower:]' '[:upper:]')
# Escape single quotes for SQL
archive_path_stored="${archive_path_stored//\'/\'\'}"
filename="${filename//\'/\'\'}"
archive_escaped="${archive//\'/\'\'}"
# Check if exists
existing=$(sqlite3 audio7z.db "SELECT COUNT(*) FROM audio_files WHERE path = '$archive_path_stored'" 2>/dev/null)
if [ "${existing:-0}" -eq 0 ]; then
# Try to extract and get metadata
TEMP_FILE="$TEMP_DIR/$filename"
7z e -y -o"$TEMP_DIR" "$archive" "$full_path" >/dev/null 2>&1
if [ -f "$TEMP_FILE" ] && command -v ffprobe >/dev/null 2>&1; then
# Extract metadata
title=$(ffprobe -v error -show_entries format_tags=title -of default=noprint_wrappers=1:nokey=1 "$TEMP_FILE" 2>/dev/null)
artist=$(ffprobe -v error -show_entries format_tags=artist -of default=noprint_wrappers=1:nokey=1 "$TEMP_FILE" 2>/dev/null)
album=$(ffprobe -v error -show_entries format_tags=album -of default=noprint_wrappers=1:nokey=1 "$TEMP_FILE" 2>/dev/null)
year=$(ffprobe -v error -show_entries format_tags=date -of default=noprint_wrappers=1:nokey=1 "$TEMP_FILE" 2>/dev/null | grep -o '[0-9]\{4\}' | head -1)
track=$(ffprobe -v error -show_entries format_tags=track -of default=noprint_wrappers=1:nokey=1 "$TEMP_FILE" 2>/dev/null | grep -o '[0-9]\+' | head -1)
genre=$(ffprobe -v error -show_entries format_tags=genre -of default=noprint_wrappers=1:nokey=1 "$TEMP_FILE" 2>/dev/null)
duration=$(ffprobe -v error -show_entries format=duration -of default=noprint_wrappers=1:nokey=1 "$TEMP_FILE" 2>/dev/null)
duration=${duration%.*}
codec=$(ffprobe -v error -show_entries stream=codec_name -of default=noprint_wrappers=1:nokey=1 "$TEMP_FILE" 2>/dev/null | head -1)
sample_rate=$(ffprobe -v error -show_entries stream=sample_rate -of default=noprint_wrappers=1:nokey=1 "$TEMP_FILE" 2>/dev/null | head -1)
channels=$(ffprobe -v error -show_entries stream=channels -of default=noprint_wrappers=1:nokey=1 "$TEMP_FILE" 2>/dev/null | head -1)
bitrate=$(ffprobe -v error -show_entries format=bit_rate -of default=noprint_wrappers=1:nokey=1 "$TEMP_FILE" 2>/dev/null | head -1)
if [[ "$bitrate" =~ ^[0-9]+$ ]] && [ "$bitrate" -gt 1000 ]; then
bitrate=$((bitrate / 1000))
fi
# Escape for SQL
title="${title//\'/\'\'}"
artist="${artist//\'/\'\'}"
album="${album//\'/\'\'}"
genre="${genre//\'/\'\'}"
codec="${codec//\'/\'\'}"
sqlite3 audio7z.db <<EOF
INSERT INTO audio_files (path, filename, directory, title, artist, album, year, track, genre, duration, size, bitrate, sample_rate, channels, codec, file_type, last_modified, created_at) VALUES (‘\(archive_path_stored', '\)filename’, ‘\(archive_escaped', '\)title’, ‘\(artist', '\)album’, ‘\(year', '\)track’, ‘\(genre', '\)duration’, \(size, '\)bitrate’, ‘\(sample_rate', '\)channels’, ‘\(codec', '\)file_type’, \((date +%s), CURRENT_TIMESTAMP); EOF rm -f "\)TEMP_FILE” else sqlite3 audio7z.db <<EOF INSERT INTO audio_files (path, filename, directory, title, artist, album, year, track, genre, duration, size, bitrate, sample_rate, channels, codec, file_type, last_modified, created_at) VALUES (‘\(archive_path_stored', '\)filename’, ‘$archive_escaped’, NULL, NULL, NULL, NULL, NULL, NULL, NULL, \(size, NULL, NULL, NULL, '\)file_type’, ‘$file_type’, $(date +%s), CURRENT_TIMESTAMP); EOF fi
((TOTAL_ADDED++))
if [ $((TOTAL_ADDED % 50)) -eq 0 ]; then
echo " Added $TOTAL_ADDED files..."
fi
fi
fi
done
done
rm -rf “$TEMP_DIR”
Stats
TOTAL_FILES=\((sqlite3 audio7z.db "SELECT COUNT(*) FROM audio_files") ARCHIVE_FILES=\)((TOTAL_FILES - EXISTING_COUNT))
echo “” echo “========================================” echo “COMPLETE” echo “========================================” echo “Database: audio7z.db” echo “Archives scanned: $ARCHIVE_COUNT” echo “Regular files: $EXISTING_COUNT” echo “Archive files: $ARCHIVE_FILES” echo “Total files: $TOTAL_FILES” echo “” echo “Example path in database:” echo “archive:///storage/5C6E-0E7C/…/Perez Prado — Selections.7z|/Perez Prado — Selections/Chivirico.ogg” echo “”
#!/bin/bash # Name: search7z.sh # Searches and plays from audio7z.db with RAW path handling
if [ $# -eq 0 ]; then echo “Usage: $0
DB=“audio7z.db” SEARCH_TERM=“$*”
if [ ! -f “$DB” ]; then echo “Error: $DB not found. Run audio7z.sh first.” exit 1 fi
Search logic
SEARCH_LOWER=\((echo "\)SEARCH_TERM” | tr ‘[:upper:]’ ‘[:lower:]’)
WORDS=() while read -r word; do [[ -n “\(word" ]] && WORDS+=("\)word”) done < <(echo “$SEARCH_LOWER” | grep -o “[a-z0-9]+”)
if [ ${#WORDS[@]} -eq 0 ]; then echo “No valid search words.” exit 1 fi
echo “Searching for: ${WORDS[@]}” echo “”
Build WHERE clause
WHERE_CLAUSE=“” for word in “${WORDS[@]}”; do WORD_CONDITION=“( (’ ’ || lower(path) || ’ ‘) LIKE’% \(word %' OR lower(path) LIKE '\)word %’ OR lower(path) LIKE ‘\(word.%' OR lower(path) LIKE '\)word/%’ OR lower(path) LIKE ‘% \(word' OR lower(path) LIKE '%.\)word’ OR lower(path) LIKE ‘%/\(word' OR lower(path) = '\)word’ OR
(' ' || lower(title) || ' ') LIKE '% $word %' OR
lower(title) LIKE '$word %' OR
lower(title) LIKE '$word.%' OR
lower(title) LIKE '$word/%' OR
lower(title) LIKE '% $word' OR
lower(title) LIKE '%.$word' OR
lower(title) LIKE '%/$word' OR
lower(title) = '$word' OR
(' ' || lower(artist) || ' ') LIKE '% $word %' OR
lower(artist) LIKE '$word %' OR
lower(artist) LIKE '$word.%' OR
lower(artist) LIKE '$word/%' OR
lower(artist) LIKE '% $word' OR
lower(artist) LIKE '%.$word' OR
lower(artist) LIKE '%/$word' OR
lower(artist) = '$word' OR
(' ' || lower(filename) || ' ') LIKE '% $word %' OR
lower(filename) LIKE '$word %' OR
lower(filename) LIKE '$word.%' OR
lower(filename) LIKE '$word/%' OR
lower(filename) LIKE '% $word' OR
lower(filename) LIKE '%.$word' OR
lower(filename) LIKE '%/$word' OR
lower(filename) = '$word' OR
(' ' || lower(album) || ' ') LIKE '% $word %' OR
lower(album) LIKE '$word %' OR
lower(album) LIKE '$word.%' OR
lower(album) LIKE '$word/%' OR
lower(album) LIKE '% $word' OR
lower(album) LIKE '%.$word' OR
lower(album) LIKE '%/$word' OR
lower(album) = '$word' OR
(' ' || lower(directory) || ' ') LIKE '% $word %' OR
lower(directory) LIKE '$word %' OR
lower(directory) LIKE '$word.%' OR
lower(directory) LIKE '$word/%' OR
lower(directory) LIKE '% $word' OR
lower(directory) LIKE '%.$word' OR
lower(directory) LIKE '%/$word' OR
lower(directory) = '$word'
)"
[[ -z "$WHERE_CLAUSE" ]] && WHERE_CLAUSE="$WORD_CONDITION" || WHERE_CLAUSE="$WHERE_CLAUSE AND $WORD_CONDITION"
done
SQL_QUERY=“SELECT path, filename, title, artist FROM audio_files WHERE $WHERE_CLAUSE ORDER BY artist, album, track, title”
Get results
mapfile -t RESULTS < <(sqlite3 -batch -noheader -separator ‘|’ “\(DB" "\)SQL_QUERY”)
if [ ${#RESULTS[@]} -eq 0 ]; then echo “No matching files found.” exit 0 fi
echo “Found ${#RESULTS[@]} files:” echo “========================”
PATHS=() for i in “\({!RESULTS[@]}"; do IFS='|' read -r path filename title artist <<< "\){RESULTS[\(i]}" PATHS+=("\)path”)
# Clean display
clean_path=$(echo "$path" | tr -d '\r')
if [[ "$clean_path" == archive://* ]]; then
# Show just the internal filename for display
if [[ -n "$title" && -n "$artist" ]]; then
echo "$((i+1)). [Archive] $artist - $title"
elif [[ -n "$title" ]]; then
echo "$((i+1)). [Archive] $title"
else
echo "$((i+1)). [Archive] $filename"
fi
else
if [[ -n "$title" && -n "$artist" ]]; then
echo "$((i+1)). $artist - $title"
elif [[ -n "$title" ]]; then
echo "$((i+1)). $title"
else
echo "$((i+1)). $filename"
fi
fi
done
echo “”
Ask to play
read -p “Play all files? [y/N]:” -n 1 -r echo “” if [[ ! \(REPLY =~ ^[Yy]\) ]]; then echo “Cancelled.” exit 0 fi
echo “Playing ${#RESULTS[@]} files…” echo “Press SHIFT+Q to quit MPV completely.” echo “”
Create input config
TMP_CONF=\((mktemp) echo "Q quit" > "\)TMP_CONF”
Play files
for path in “\({PATHS[@]}"; do # CRITICAL: Use the EXACT path from database, just clean carriage returns target_path=\)(echo”$path” | tr -d ’)
# Display what's being played
if [[ "$target_path" == archive://* ]]; then
# Extract archive name and internal file for display
archive_part="${target_path#archive://}"
archive_file="${archive_part%%\\|*}"
internal_part="${archive_part#*\\|}"
internal_part="${internal_part#/}" # Remove leading slash
echo "Playing from archive: $(basename "$archive_file") -> $internal_part"
else
echo "Playing: $(basename "$target_path")"
fi
# CRITICAL FIX: Convert stored escaped pipe to literal pipe for mpv
# Database stores: archive:///path\|/internal/path
# mpv needs: archive:///path|/internal/path
# Use sed to replace escaped pipe with literal pipe
final_path=$(echo "$target_path" | sed 's/\\|/|/g')
# Play with mpv
mpv --no-video --input-conf="$TMP_CONF" "$final_path"
# Check if user quit
if [ $? -eq 3 ]; then
echo "Playback stopped by user."
break
fi
done
rm -f “$TMP_CONF”
the machine is persisting with the same error.
- output
- $ rm search7z.sh
- $ nano search7z.sh
- $ chmod +x search7z.sh
- $ ./search7.sh chivirico bash: ./search7.sh: No such file or directory
-
$ ./search7z.sh chivirico Searching for: chivirico
Found 1 files:
- [Archive] Chivirico.ogg
Play all files? [y/N]: y Playing 1 files… Press SHIFT+Q to quit MPV completely.
Playing from archive: Perez Prado — Selections.7z ->
storage/5C6E-0E7C/favoritemusic/7z/Perez Prado — Selections.7z
Failed to open archive:///storage/5C6E-0E7C/favoritemusic/7z/Perez Prado
— Selections.7z. Exiting… (Errors when loading file)
again, the correct path is this and it worked. the machine is not respecting this precise syntax:
…/favoritemusic/7z $ mpv Perez Prado — Selections.7z Playing: archive:///storage/5C6E-0E7C/favoritemusic/7z/Perez Prado — Selections.7z|/Perez Prado — Selections/Chivirico.ogg [libarchive] possibly unsupported seeking - switching to reopening ● Audio –aid=1 ‘Chivirico’ (vorbis 2ch 44100 Hz 112 kbps) File tags: Artist: Perez Prado Album: Best Selection Date: 2009 Genre: Jazz Title: Chivirico Track: 27 AO: [opensles] 44100Hz stereo 2ch float A: 00:00:07 / 00:02:02 (6%) Cache: 115s/5MB Playing: archive:///storage/5C6E-0E7C/favoritemusic/7z/Perez Prado — Selections.7z|/Perez Prado — Selections/Copacabana.ogg [libarchive] possibly unsupported seeking - switching to reopening ● Audio –aid=1 ‘Copacabana’ (vorbis 2ch 44100 Hz 112 kbps) File tags: Artist: Perez Prado Album: Best Selection Date: 2009 Genre: Jazz Title: Copacabana Track: 08 A: 00:00:02 / 00:03:21 (1%) Cache: 198s/10MB Exiting… (Quit) …/favoritemusic/7z $ mpv archive:///storage/5C6E-0E7C/favoritemusic/7z/Perez Prado — Selections.7z|/Perez Prado — Selections/Chivirico.ogg bash: /Perez: No such file or directory …/favoritemusic/7z $ mpv archive:///storage/5C6E-0E7C/favoritemusic/7z/Perez Prado — Selections.7z|/Perez Prado — Selections/Chivirico.ogg Playing: archive:///storage/5C6E-0E7C/favoritemusic/7z/Perez Failed to open archive:///storage/5C6E-0E7C/favoritemusic/7z/Perez. Playing: Prado [file] Cannot open file ‘Prado’: No such file or directory Failed to open Prado. Playing: — [file] Cannot open file ‘—’: No such file or directory Failed to open —. Playing: Selections.7z|/Perez [file] Cannot open file ‘Selections.7z|/Perez’: No such file or directory Failed to open Selections.7z|/Perez. Playing: Prado [file] Cannot open file ‘Prado’: No such file or directory Failed to open Prado. Playing: — [file] Cannot open file ‘—’: No such file or directory Failed to open —. Playing: Selections/Chivirico.ogg [file] Cannot open file ‘Selections/Chivirico.ogg’: No such file or directory Failed to open Selections/Chivirico.ogg. Exiting… (Errors when loading file) …/favoritemusic/7z $ mpv archive:///storage/5C6E-0E7C/favoritemusic/7z/Perez Prado — Selections.7z|/Perez Prado — Selections/Chivirico.ogg client removed during hook handling Playing: archive:///storage/5C6E-0E7C/favoritemusic/7z/Perez Prado — Selections.7z|/Perez [libarchive] archive entry not found. ‘Perez’ Failed to open archive:///storage/5C6E-0E7C/favoritemusic/7z/Perez Prado — Selections.7z|/Perez. Playing: Prado — Selections/Chivirico.ogg [file] Cannot open file ‘Prado — Selections/Chivirico.ogg’: No such file or directory Failed to open Prado — Selections/Chivirico.ogg. Exiting… (Errors when loading file) …/favoritemusic/7z $ mpv archive:///storage/5C6E-0E7C/favoritemusic/7z/Perez Prado — Selections.7z|/Perez Prado — Selections/Chivirico.ogg [libarchive] possibly unsupported seeking - switching to reopening ● Audio –aid=1 ‘Chivirico’ (vorbis 2ch 44100 Hz 112 kbps) File tags: Artist: Perez Prado Album: Best Selection Date: 2009 Genre: Jazz Title: Chivirico Track: 27 AO: [opensles] 44100Hz stereo 2ch float A: 00:00:01 / 00:02:02 (1%) Cache: 120s/6MB Exiting… (Quit)
please note that when manually opening with mpv cli and proper syntax, the audio file can be opened.
the ” ” symbol after typing the “file.7z” part is crucial in the command:
$ mpv archive:///storage/5C6E-0E7C/favoritemusic/7z/Perez Prado — Selections.7z|/Perez Prado — Selections/Chivirico.ogg
make all the adjustments necessary, please for the scripts to work.