My Blog

A classic static blog

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 ” echo “Example: $0 chivirico” exit 1 fi

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:

  1. [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.