jhdhdjj33333
The issue is a classic “shell vs. literal” conflict. When you type the command manually, those backslashes ( and |) are escapes for the shell. They tell Bash “don’t split the name at the space” and “don’t treat the pipe as a command redirect.” However, when a script stores a string in a variable and you use “\(variable", the shell handles the quoting for you. If your variable contains literal backslashes (like Perez\ Prado), the shell passes those backslashes literally to mpv, and mpv fails because the file on disk doesn't actually have backslashes in its name. 🛠️ The Fix: Raw Database and Quoted Variables We need to change two things: * audio7z.sh: Store the path raw (no backslashes for spaces). * search7z.sh: Use the literal pipe separator | and wrap the path in double quotes. 1. Update audio7z.sh (The Indexer) In your indexer, find the line where you define archive_path_stored. We want it to store the real path. Find this: archive_path_stored="archive://\)archive\|/$full_path”
Change it to this: # We use a single | because we will handle the shell escape # via double-quotes during playback. archive_path_stored=“archive://\(archive|/\)full_path”
Update search7z.sh (The Player) In your search script, the logic that replaces | with | is good, but we must ensure we aren’t accidentally stripping spaces or adding unwanted escapes. Replace your playback loop with this exact logic: # … (inside the play loop of search7z.sh) for path in “\({PATHS[@]}"; do # 1. Clean up any weird carriage returns and ensure # the separator is a literal pipe. target_path=\)(echo”$path” | tr -d ‘ | sed ’s/\|/|/g’)
# 2. Display logic (optional, for your visibility) echo “Attempting to play: $target_path”
# 3. THE CRITICAL PART: # Use quotes “\(target_path". This handles the spaces automatically. # We do NOT want to add backslashes to the variable itself. mpv --no-video --input-conf="\)TMP_CONF” “$target_path”
if [ $? -eq 3 ]; then echo “Playback stopped by user.” break fi done
🔍 Why this works When you run: mpv “archive:///storage/5C6E-0E7C/path with spaces.7z|/internal folder/file.ogg” * The double quotes tell Bash: “Everything inside here is ONE argument. Ignore the spaces.” * The literal pipe | stays a pipe because it’s inside quotes. mpv sees that pipe and knows it’s the divider for the archive protocol. * The internal spaces are preserved without needing those messy characters. One Final Step Since your database currently has paths with | and potentially wrong folder segments, you should: * Update the audio7z.sh as shown above. * Delete your old database: rm audio7z.db. * Re-run the indexer: ./audio7z.sh.
Here are the corrected versions of both scripts. The primary fix is shifting away from manual backslash escaping ( ) and instead relying on Bash’s double-quoting mechanism. This ensures that spaces and special characters are treated as literal parts of the filename when passed to mpv. 1. The Indexer: audio7z.sh This script now stores the path with a literal pipe |. This is the standard internal format mpv expects for its archive protocol. #!/bin/bash # Name: audio7z.sh # Creates audio7z.db with CLEAN literal paths
echo “Creating audio7z.db database…” echo “========================================”
if [ ! -f “audio.db” ]; then echo “Error: audio.db not found!” exit 1 fi
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
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
echo “Copying from audio.db…” sqlite3 audio.db “.dump audio_files” | grep -E “^INSERT” | sqlite3 audio7z.db
echo “Scanning .7z archives in /storage/5C6E-0E7C…” TEMP_DIR=$(mktemp -d)
find /storage/5C6E-0E7C -type f -name “*.7z” | while read -r archive; do echo “Processing: \((basename "\)archive”)”
# Use -slt to get technical list and parse the 'Path =' line
7z l -slt "$archive" 2>/dev/null | grep "^Path = " | while read -r line; do
full_path="${line#Path = }"
# Skip the archive itself or directories
if [[ "$full_path" == *.7z ]] || [[ "$full_path" == "" ]]; then continue; fi
# Filter for audio extensions
if [[ "$full_path" =~ \.(opus|ogg|flac|wav|m4a|oga|mka|mp3|aac|wma)$ ]]; then
# STORE AS LITERAL: archive:///path/to/file.7z|/internal/path/file.ogg
# No manual backslashes for spaces; quotes will handle them later.
archive_path_stored="archive://$archive|/$full_path"
filename=$(basename "$full_path")
archive_escaped="${archive//\'/\'\'}"
path_sql="${archive_path_stored//\'/\'\'}"
name_sql="${filename//\'/\'\'}"
# Extraction and FFPROBE metadata logic
7z e -y -o"$TEMP_DIR" "$archive" "$full_path" >/dev/null 2>&1
TEMP_FILE="$TEMP_DIR/$filename"
if [ -f "$TEMP_FILE" ]; then
# (Simplified metadata extraction for brevity)
artist=$(ffprobe -v error -show_entries format_tags=artist -of default=noprint_wrappers=1:nokey=1 "$TEMP_FILE" 2>/dev/null | head -1 | sed "s/'/''/g")
title=$(ffprobe -v error -show_entries format_tags=title -of default=noprint_wrappers=1:nokey=1 "$TEMP_FILE" 2>/dev/null | head -1 | sed "s/'/''/g")
sqlite3 audio7z.db "INSERT INTO audio_files (path, filename, directory, artist, title) VALUES ('$path_sql', '$name_sql', '$archive_escaped', '$artist', '$title');"
rm -f "$TEMP_FILE"
fi
fi
done
done rm -rf “$TEMP_DIR” echo “Done.”
- The Searcher: search7z.sh This script retrieves the literal path and wraps it in double quotes when calling mpv. This mimics your successful manual command exactly. #!/bin/bash # Name: search7z.sh
if [ $# -eq 0 ]; then echo “Usage: $0
DB=“audio7z.db” SEARCH_TERM=“$*”
Extract words for SQLite query
WORDS=(\((echo "\)SEARCH_TERM” | tr ‘[:upper:]’ ‘[:lower:]’ | grep -o “[a-z0-9]+”))
WHERE_CLAUSE=“” for word in “\({WORDS[@]}"; do COND="(lower(path) LIKE '%\)word%’ OR lower(title) LIKE ‘%\(word%' OR lower(artist) LIKE '%\)word%’)” [[ -z “\(WHERE_CLAUSE" ]] && WHERE_CLAUSE="\)COND” || WHERE_CLAUSE=“$WHERE_CLAUSE AND $COND” done
Fetch results
mapfile -t RESULTS < <(sqlite3 -batch -noheader -separator ‘|’ “$DB” “SELECT path, artist, title FROM audio_files WHERE $WHERE_CLAUSE”)
if [ ${#RESULTS[@]} -eq 0 ]; then echo “No files found.” exit 0 fi
Show and Play
for i in “\({!RESULTS[@]}"; do IFS='|' read -r path artist title <<< "\){RESULTS[\(i]}" echo "\)((i+1)). $artist - $title” done
read -p “Play all? [y/N]:” -n 1 -r; echo “” [[ ! \(REPLY =~ ^[Yy]\) ]] && exit 0
TMP_CONF=\((mktemp) echo "Q quit" > "\)TMP_CONF”
for row in “\({RESULTS[@]}"; do IFS='|' read -r path artist title <<< "\)row”
# Remove carriage returns
target_path=$(echo "$path" | tr -d '\r')
# Convert any accidental escaped pipes '\|' to literal pipes '|'
final_path="${target_path//\\|/|}"
echo "Playing: $artist - $title"
# THE CRITICAL STEP: Wrap in double quotes.
# This sends the path to MPV exactly as a single string.
mpv --no-video --input-conf="$TMP_CONF" "$final_path"
[[ $? -eq 3 ]] && break
done
rm -f “$TMP_CONF”
⚠️ Important: Reset your Database Since your current database contains the “wrong” folder structure (missing the Perez Prado — part) and escaped backslashes, you must delete it and re-index for these changes to take effect: * rm audio7z.db * ./audio7z.sh * ./search7z.sh chivirico