Share your shell/bash/bat scripts

I’m trying to get help I promise

Hey! I also have TWO Windows laptops!

The more Windows PC’s you have, the bigger the chance that you have a Linux machine.

script to set all artist tags to based on its folder name



how it works

VAST_AUDIO_LIBRARY/                    ← Run script HERE (current directory)
│
├── folder_to_artist_tag.sh            ← The script file (place here)
│
├── 8th day/                           ← FOLDER = Artist name "8th day"
│   ├── We All Belong.mp3              ← Check: artist tag = "8th day"? 
│   ├── All You Got/                   ← Subfolder (script searches recursively)
│   │   ├── 01 - Mazal Tov.mp3        ← Check: artist tag = "8th day"?
│   │   ├── 02 - Bounce.mp3           ← If tag = "8th Day" → UPDATE to "8th day"
│   │   └── 03 - Harmony.mp3          ← If tag = "8th day" → SKIP (already correct)
│   └── Brooklyn/
│       ├── 01 - Brooklyn.mp3
│       └── 02 - Don't Say Goodbye.mp3
│
├── Avraham Fried/                     ← FOLDER = Artist name "Avraham Fried"
│   ├── song1.mp3                      ← Check: artist tag = "Avraham Fried"?
│   ├── song2.mp3                      ← If wrong → UPDATE to "Avraham Fried"
│   └── Album Name/
│       └── track.mp3                  ← Also checked (recursive search)
│
├── Mordechai Ben David/               ← FOLDER = Artist name "Mordechai Ben David"
│   ├── track1.mp3                     ← All files here get artist = "Mordechai Ben David"
│   └── track2.mp3
│
└── Yaakov Shwekey/                    ← Each top-level folder = one artist
    └── songs/
        └── song.mp3


HOW IT WORKS:
═════════════

1. START in VAST_AUDIO_LIBRARY/
   │
   ├─→ Find all folders (8th day/, Avraham Fried/, etc.)
   │
   └─→ For EACH folder:
       │
       ├─→ Folder name = Expected Artist Name
       │
       ├─→ Find ALL audio files inside (recursively)
       │   (searches subfolders too)
       │
       └─→ For EACH audio file:
           │
           ├─→ Read current artist tag
           │
           ├─→ Does it match folder name?
           │   │
           │   ├─→ YES: Skip (already correct)
           │   │
           │   └─→ NO: Update tag to match folder name
           │
           └─→ Move to next file


EXECUTION:
══════════

Terminal view:
┌─────────────────────────────────────────────────────────┐
│ ploiny@computer:/media/VAST_AUDIO_LIBRARY$ │
│                                                          │
│ $ bash folder_to_artist_tag.sh                          │
│                                                          │
│ [CHECK] Looking for tools...                            │
│ [OK] eyeD3 found!                                       │
│ [INFO] Using tool: eyeD3                                │
│                                                          │
│ [FOLDER 1/294] Processing: '8th day'                   │
│   [FILE 1/104] Checking: 8th day/song.mp3              │
│     Current: '8th Day' → Updating to '8th day'         │
│     [SUCCESS] Updated!                                  │
│                                                          │
│   [FILE 2/104] Checking: 8th day/song2.mp3             │
│     Current: '8th day' → Already correct, skipping     │
│                                                          │
│ [FOLDER 2/294] Processing: 'Avraham Fried'             │
│   ...                                                   │
└─────────────────────────────────────────────────────────┘


IMPORTANT RULES:
════════════════

✓ One artist = One top-level folder
✓ Folder name becomes the artist tag for ALL files inside
✓ Subfolders are OK (albums, etc.) - script searches recursively
✓ Files already matching = skipped (no unnecessary rewrites)
✓ Script must have WRITE permission to the files
✓ Works on: MP3, M4A, FLAC, OGG, WAV


EXAMPLE CORRECTION:
═══════════════════

BEFORE running script:
  Folder: "8th day"
  File: "8th day/song.mp3" has tag: artist="8th Day"
                                            ↑
                                     (capital D)

AFTER running script:
  Folder: "8th day"
  File: "8th day/song.mp3" has tag: artist="8th day"
                                            ↑
                                     (lowercase d - matches folder!)

basically if you want to browse your organized artists in music players the same way you do in file managers (like me) this should be helpful

execute doing “bash path/to/sript.sh” not “./script”



very important: proper placement of script is crucial!!

Script
#!/bin/bash

echo "=========================================="
echo "Artist Tag Fixer - Starting"
echo "=========================================="
echo ""

# Check for available tools (prioritized by reliability and speed)
echo "[CHECK] Scanning for available audio tagging tools..."
echo ""

TOOL=""
TOOL_NAME=""

# Priority 1: eyeD3 - best for MP3, modifies in-place, works well on FAT32
echo "[CHECK] Looking for eyeD3..."
if command -v eyeD3 &> /dev/null; then
    echo "[OK] eyeD3 found!"
    TOOL="eyeD3"
    TOOL_NAME="eyeD3"
fi

# Priority 2: mid3v2 - also good for MP3, modifies in-place
if [ -z "$TOOL" ]; then
    echo "[CHECK] Looking for mid3v2..."
    if command -v mid3v2 &> /dev/null; then
        echo "[OK] mid3v2 found!"
        TOOL="mid3v2"
        TOOL_NAME="mid3v2"
    fi
fi

# Priority 3: kid3-cli - versatile, handles many formats
if [ -z "$TOOL" ]; then
    echo "[CHECK] Looking for kid3-cli..."
    if command -v kid3-cli &> /dev/null; then
        echo "[OK] kid3-cli found!"
        TOOL="kid3-cli"
        TOOL_NAME="kid3-cli"
    fi
fi

# Priority 4: exiftool - works but slower
if [ -z "$TOOL" ]; then
    echo "[CHECK] Looking for exiftool..."
    if command -v exiftool &> /dev/null; then
        echo "[OK] exiftool found!"
        TOOL="exiftool"
        TOOL_NAME="exiftool"
    fi
fi

# Priority 5: ffmpeg - requires write permissions, creates temp files
if [ -z "$TOOL" ]; then
    echo "[CHECK] Looking for ffmpeg..."
    if command -v ffmpeg &> /dev/null; then
        echo "[OK] ffmpeg found!"
        TOOL="ffmpeg"
        TOOL_NAME="ffmpeg"
    fi
fi

# If no tool found, exit
if [ -z "$TOOL" ]; then
    echo ""
    echo "[ERROR] No supported audio tagging tools found!"
    echo "[INFO] Please install one of the following (in order of preference):"
    echo "  1. eyeD3:    sudo apt install eyed3      (RECOMMENDED for FAT32/vfat)"
    echo "  2. mid3v2:   sudo apt install python3-mutagen"
    echo "  3. kid3-cli: sudo apt install kid3-cli"
    echo "  4. exiftool: sudo apt install libimage-exiftool-perl"
    echo "  5. ffmpeg:   sudo apt install ffmpeg     (may not work on FAT32)"
    exit 1
fi

echo ""
echo "[INFO] Using tool: $TOOL_NAME"
echo ""

# Check write permissions on current directory
echo "[CHECK] Testing write permissions in current directory..."
TEST_FILE=".artist_tag_fixer_test_$$"
if touch "$TEST_FILE" 2>/dev/null; then
    rm -f "$TEST_FILE"
    echo "[OK] Write permissions confirmed"
else
    echo "[ERROR] Cannot write to current directory!"
    echo "[INFO] This script needs write access to modify audio files."
    echo "[INFO] Current directory: $(pwd)"
    echo ""
    echo "[SUGGESTION] Try one of these solutions:"
    echo "  1. If on SD card/USB: sudo mount -o remount,rw /media/sam/THE_BIG_ONE"
    echo "  2. Copy files to home directory, modify there, then copy back"
    echo "  3. Run with sudo (not recommended for user files)"
    exit 1
fi
echo ""

# Warn if using ffmpeg on FAT32
if [ "$TOOL" = "ffmpeg" ]; then
    FILESYSTEM=$(df -T . | tail -1 | awk '{print $2}')
    echo "[INFO] Detected filesystem: $FILESYSTEM"
    if [[ "$FILESYSTEM" =~ ^(vfat|fat|msdos|exfat)$ ]]; then
        echo "[WARN] You're using ffmpeg on a FAT filesystem ($FILESYSTEM)"
        echo "[WARN] ffmpeg may fail because it creates temporary files"
        echo "[WARN] STRONGLY RECOMMENDED: Install eyeD3 or mid3v2 instead:"
        echo "       sudo apt install eyed3"
        echo ""
        read -p "[PROMPT] Continue anyway? (y/N): " -n 1 -r
        echo
        if [[ ! $REPLY =~ ^[Yy]$ ]]; then
            echo "[INFO] Exiting. Please install eyeD3 or mid3v2."
            exit 1
        fi
    fi
fi
echo ""

# Function to get artist tag based on tool
get_artist() {
    local file="$1"
    case "$TOOL" in
        eyeD3)
            eyeD3 --no-color "$file" 2>/dev/null | grep -oP '(?<=artist: ).*' | head -1
            ;;
        mid3v2)
            mid3v2 -l "$file" 2>/dev/null | grep "TPE1=" | cut -d'=' -f2
            ;;
        kid3-cli)
            kid3-cli -c "get artist" "$file" 2>/dev/null | tail -1
            ;;
        exiftool)
            exiftool -Artist -s3 "$file" 2>/dev/null
            ;;
        ffmpeg)
            ffprobe -v quiet -show_entries format_tags=artist -of default=noprint_wrappers=1:nokey=1 "$file" 2>/dev/null
            ;;
    esac
}

# Function to set artist tag based on tool
set_artist() {
    local file="$1"
    local artist="$2"
    case "$TOOL" in
        eyeD3)
            eyeD3 --artist "$artist" --quiet "$file" 2>/dev/null
            ;;
        mid3v2)
            mid3v2 --artist "$artist" "$file" 2>/dev/null
            ;;
        kid3-cli)
            kid3-cli -c "set artist \"$artist\"" "$file" 2>/dev/null
            ;;
        exiftool)
            exiftool -Artist="$artist" -overwrite_original "$file" 2>/dev/null
            ;;
        ffmpeg)
            local temp_file="${file}.tmp"
            ffmpeg -i "$file" -metadata artist="$artist" -codec copy "$temp_file" 2>/dev/null && mv "$temp_file" "$file"
            ;;
    esac
}

# Get current directory
current_dir=$(pwd)
echo "[INFO] Working directory: $current_dir"
echo ""

# Count folders
folder_count=$(find . -maxdepth 1 -type d ! -name "." ! -name ".*" | wc -l)
echo "[INFO] Found $folder_count artist folder(s) to process"
echo ""

# Process each directory
processed_folders=0
processed_files=0
updated_files=0
failed_updates=0

for artist_dir in */; do
    # Skip hidden directories
    [[ "$artist_dir" == .* ]] && continue
    
    # Remove trailing slash to get folder name
    artist_name="${artist_dir%/}"
    
    processed_folders=$((processed_folders + 1))
    
    echo "=========================================="
    echo "[FOLDER $processed_folders/$folder_count] Processing: '$artist_name'"
    echo "=========================================="
    
    # Count files in this directory
    file_count=$(find "$artist_dir" -type f \( -iname "*.mp3" -o -iname "*.m4a" -o -iname "*.flac" -o -iname "*.ogg" -o -iname "*.wav" \) | wc -l)
    echo "[INFO] Found $file_count audio file(s) in this folder"
    echo ""
    
    if [ $file_count -eq 0 ]; then
        echo "[WARN] No audio files found in '$artist_name', skipping..."
        echo ""
        continue
    fi
    
    # Find all audio files recursively in this artist folder
    file_num=0
    find "$artist_dir" -type f \( -iname "*.mp3" -o -iname "*.m4a" -o -iname "*.flac" -o -iname "*.ogg" -o -iname "*.wav" \) | while read -r file; do
        file_num=$((file_num + 1))
        
        echo "[FILE $file_num/$file_count] Checking: $file"
        
        # Get current artist tag
        echo "  [ACTION] Reading current artist tag using $TOOL_NAME..."
        current_artist=$(get_artist "$file")
        
        if [ -z "$current_artist" ]; then
            echo "  [INFO] No artist tag found (empty)"
            current_artist="(empty)"
        else
            echo "  [INFO] Current artist tag: '$current_artist'"
        fi
        
        # Check if artist tag matches folder name
        if [ "$current_artist" != "$artist_name" ]; then
            echo "  [MISMATCH] Artist tag does not match folder name!"
            echo "  [ACTION] Updating artist tag using $TOOL_NAME..."
            echo "    FROM: '$current_artist'"
            echo "    TO:   '$artist_name'"
            
            set_artist "$file" "$artist_name"
            
            if [ $? -eq 0 ]; then
                # Verify the update worked
                verify_artist=$(get_artist "$file")
                if [ "$verify_artist" = "$artist_name" ]; then
                    echo "  [SUCCESS] Artist tag updated and verified!"
                    updated_files=$((updated_files + 1))
                else
                    echo "  [ERROR] Update appeared to succeed but verification failed!"
                    echo "  [DEBUG] Expected: '$artist_name', Got: '$verify_artist'"
                    failed_updates=$((failed_updates + 1))
                fi
            else
                echo "  [ERROR] Failed to update artist tag!"
                failed_updates=$((failed_updates + 1))
            fi
        else
            echo "  [OK] Artist tag already matches folder name, no update needed"
        fi
        
        echo ""
        processed_files=$((processed_files + 1))
    done
    
    echo ""
done

echo "=========================================="
echo "Summary"
echo "=========================================="
echo "[COMPLETE] All folders processed!"
echo "[TOOL] Used: $TOOL_NAME"
echo "[STATS] Folders processed: $processed_folders"
echo "[STATS] Files checked: $processed_files"
echo "[STATS] Files updated successfully: $updated_files"
echo "[STATS] Files failed to update: $failed_updates"
echo ""

if [ $failed_updates -gt 0 ]; then
    echo "[WARN] Some updates failed!"
    echo "[INFO] This is likely due to:"
    echo "  - Filesystem limitations (FAT32/vfat with ffmpeg)"
    echo "  - File permission issues"
    echo "  - Incompatible file formats"
    echo ""
    echo "[SUGGESTION] Install eyeD3 for better FAT32 support:"
    echo "  sudo apt install eyed3"
    echo ""
fi

echo "Done!"

Qin Device Identifiers script
Automatically collects phone information (IMEI, Bluetooth address, WiFi address) and saves it to a text file. usefull for saving the correct info when flashing us bands and then using sn write tool to replace these identifiers

How to use:

  1. Connect your phone to the computer and make sure ADB is connected
  2. Run the script
  3. Enter the person’s name when asked
  4. Enter the WiFi MAC address when asked (find it in Settings > About Phone)
  5. Done! The information is saved to “imei numbers.txt”
Qin device identifiers script
@echo off
setlocal enabledelayedexpansion

echo ========================================
echo Device Information Collection Tool
echo ========================================
echo.

REM Check if ADB device is connected
:check_device
adb devices | findstr /R "unauthorized" >nul
if !errorlevel! equ 0 (
    echo ERROR: Device detected but UNAUTHORIZED
    echo Please unlock your phone and approve the USB debugging prompt
    echo.
    pause
    echo Retrying...
    echo.
    goto :check_device
)

adb devices | findstr /R "device$" >nul
if errorlevel 1 (
    echo ERROR: No device detected
    echo Please connect your device and enable USB debugging
    echo.
    pause
    echo Retrying...
    echo.
    goto :check_device
)

echo Device detected and authorized!
echo.

echo Collecting device information...
echo.

REM Create temp file
set TEMP_FILE=%TEMP%\adb_device_info_%RANDOM%.txt

REM ===== Get IMEI =====
echo [1/3] Getting IMEI...
set IMEI=

REM Get IMEI using service call
adb shell "service call iphonesubinfo 1" > "%TEMP_FILE%"

REM Extract IMEI from the ASCII parts (between single quotes)
for /f "tokens=*" %%a in ('type "%TEMP_FILE%" ^| findstr "'"') do (
    set "line=%%a"
    REM Extract part after first quote
    for /f "tokens=2 delims='" %%b in ("!line!") do (
        set "part=%%b"
        REM Remove all dots and spaces
        set "part=!part:.=!"
        set "part=!part: =!"
        set IMEI=!IMEI!!part!
    )
)

REM Clean IMEI - keep only digits
set IMEI_TEMP=!IMEI!
set IMEI=
:extract_digits
if defined IMEI_TEMP (
    set "char=!IMEI_TEMP:~0,1!"
    set "IMEI_TEMP=!IMEI_TEMP:~1!"
    if "!char!" geq "0" if "!char!" leq "9" (
        set IMEI=!IMEI!!char!
    )
    goto :extract_digits
)

REM Take first 15 digits
set IMEI=!IMEI:~0,15!

REM ===== Get Bluetooth MAC =====
echo [2/3] Getting Bluetooth MAC address...
set BT_MAC=

REM Get Bluetooth MAC from settings
adb shell "settings get secure bluetooth_address" > "%TEMP_FILE%" 2>nul
set /p BT_MAC=<"%TEMP_FILE%"

REM Remove colons and spaces
set BT_MAC=!BT_MAC::=!
set BT_MAC=!BT_MAC: =!
call :lowercase BT_MAC

REM ===== Get WiFi MAC =====
echo [3/3] Getting WiFi MAC address...
set WIFI_MAC=

REM WiFi MAC cannot be read from Android without root
echo WiFi MAC cannot be read from Android without root - will prompt for manual entry

REM Clean up temp file
del "%TEMP_FILE%" 2>nul

echo.
echo ========================================
echo Auto-Collected Information:
echo ========================================
echo IMEI: !IMEI!
echo Bluetooth MAC: !BT_MAC!
echo WiFi MAC: !WIFI_MAC!
echo ========================================
echo.

REM Verify auto-collected data
if "!IMEI!"=="" (
    echo ERROR: Failed to retrieve IMEI
    pause
    exit /b
)
if "!BT_MAC!"=="" (
    echo ERROR: Failed to retrieve Bluetooth MAC address
    pause
    exit /b
)

REM Verify IMEI is 15 digits
set IMEI_LENGTH=0
set "temp=!IMEI!"
:count_loop
if defined temp (
    set /a IMEI_LENGTH+=1
    set "temp=!temp:~1!"
    goto :count_loop
)

if !IMEI_LENGTH! neq 15 (
    echo WARNING: IMEI should be 15 digits but got !IMEI_LENGTH! digits
    echo IMEI: !IMEI!
    echo.
    set /p "CONTINUE=Continue anyway? (Y/N): "
    if /i "!CONTINUE!" neq "Y" (
        exit /b
    )
)

REM Ask for WiFi MAC if not retrieved automatically
if "!WIFI_MAC!"=="" (
    echo.
    echo ========================================
    echo WiFi MAC Manual Entry Required
    echo ========================================
    echo Please manually enter the WiFi MAC from Settings ^> About Phone
    echo ========================================
    echo.

    :ask_wifi_mac
    set /p WIFI_MAC="Enter WiFi MAC address: "

    REM Remove colons, spaces, and dashes if user entered them
    set WIFI_MAC=!WIFI_MAC::=!
    set WIFI_MAC=!WIFI_MAC:-=!
    set WIFI_MAC=!WIFI_MAC: =!
    call :lowercase WIFI_MAC

    REM Verify WiFi MAC is 12 characters (6 bytes in hex)
    set WIFI_LENGTH=0
    set "temp=!WIFI_MAC!"
    :count_wifi
    if defined temp (
        set /a WIFI_LENGTH+=1
        set "temp=!temp:~1!"
        goto :count_wifi
    )

    if !WIFI_LENGTH! neq 12 (
        echo ERROR: WiFi MAC should be 12 characters but got !WIFI_LENGTH!
        echo WiFi MAC: !WIFI_MAC!
        echo Please enter it again without colons or spaces
        echo.
        goto :ask_wifi_mac
    )
)

REM Ask for person's name
set /p PERSON_NAME="Enter the person's name: "

echo.
echo ========================================
echo Adding Entry:
echo ========================================
echo Name: !PERSON_NAME!
echo IMEI: !IMEI!
echo Bluetooth MAC: !BT_MAC!
echo WiFi MAC: !WIFI_MAC!
echo ========================================
echo.

REM Create the entry
set OUTPUT_FILE=%~dp0imei numbers.txt

REM Create file if it doesn't exist
if not exist "!OUTPUT_FILE!" (
    echo Device Information Log > "!OUTPUT_FILE!"
    echo ======================== >> "!OUTPUT_FILE!"
)

echo.>> "!OUTPUT_FILE!"
echo !PERSON_NAME!>> "!OUTPUT_FILE!"
echo imei - !IMEI!>> "!OUTPUT_FILE!"
echo bluetooth address - !BT_MAC!>> "!OUTPUT_FILE!"
echo wifi mac address - !WIFI_MAC!>> "!OUTPUT_FILE!"

echo.
echo ========================================
echo SUCCESS! Entry added to imei numbers.txt
echo ========================================

exit /b

REM Subroutine to convert to lowercase
:lowercase
set %~1=!%~1:A=a!
set %~1=!%~1:B=b!
set %~1=!%~1:C=c!
set %~1=!%~1:D=d!
set %~1=!%~1:E=e!
set %~1=!%~1:F=f!
goto :eof

i coudnt get the wifi mac address with regualr adb needs root dont know why

Was it connected to wifi?

yup

i could see it in about phone. i even tried having claude read the screen but it wasnt going well also probalby wouldnt work as a script

So am start that settings activity, input swipe (figure out measurement) and take screencap with adb :slight_smile:

Yeshivish

exactly what i tried. but how do you make a shell script read a screenshot

Ah, good point. I was just thinking to save it in the folder.

@moderators can we move the python scripts into a new topic similar to this 1 but for python scripts? I think its its own thing. Obviously also only for cli style scripts… (not just random gui apps that happened to have been written in python)

This

My personal wrapper for yt-dlp instead of remembering their complex options which I usually need to download.

Uses basic option for downloading with thumbnail and metadata. Allows basic arguments like output directory quiet mode video or audio etc. Just see usage at the top of the script.

#!/usr/bin/env bash

# Dependencies: yt-dlp, ffmpeg

usage() {
    cat <<EOF
Usage: $(basename "$0") [-a|-v] [-q] [-o DIR] [TITLE|URL]

A yt-dlp wrapper for downloading audio or video from YouTube.

Options:
  -a, --audio          Download as MP3 audio (default)
  -v, --video          Download as MP4 video (720p)
  -q, --quiet          Suppress yt-dlp output, show only status messages
  -o, --output DIR     Output directory (must exist)
  -h, --help           Show this help message

Arguments:
  URL                  Download directly from a YouTube URL
  TITLE                Search YouTube and pick from 7 results

If no arguments are given, you will be prompted for format and title/URL.

Dependencies:
  yt-dlp               https://github.com/yt-dlp/yt-dlp
  ffmpeg               https://ffmpeg.org
EOF
}

quiet=0 outdir=""
rq='^--?q(uiet)?$' ro='^--?o(utput)?$'

# Pre-scan for -q and -o so they can appear anywhere
args=()
while [[ $# -gt 0 ]]; do
    if [[ "$1" =~ $rq ]]; then
        quiet=1
    elif [[ "$1" =~ $ro ]]; then
        if [[ -z "$2" || "$2" == -* ]]; then
            echo "Error: --output requires a directory path" >&2; exit 1
        fi
        if [[ ! -d "$2" ]]; then
            echo "Error: output directory does not exist: $2" >&2; exit 1
        fi
        outdir="$2"; shift
    elif [[ "$1" =~ ^--?h(elp)?$ ]]; then
        usage; exit 0
    else
        args+=("$1")
    fi
    shift
done
set -- "${args[@]}"

declare -a cmd=(yt-dlp -x --audio-format mp3 --embed-metadata --embed-thumbnail --no-playlist)
rv='^--?v(id(eo)?)?$' ra='^--?a(ud(io)?)?$'

if [[ $# -eq 0 ]]; then
    read -rp "Format - (a)udio or (v)ideo: " fmt
    [[ "${fmt/quit/q}" == "q" ]] && exit 0
    read -rp "Title, URL, or q to quit: " query
    [[ "${query/quit/q}" == "q" ]] && exit 0
    set -- "$fmt" "$query"
fi

if [[ "$1" =~ $rv || "${@: -1}" =~ $rv ]]; then
    cmd=(yt-dlp -S "res:720" --merge-output-format mp4 --embed-metadata --embed-thumbnail --no-playlist)
    [[ "$1" =~ $rv ]] && shift || set -- "${@:1:$#-1}"
fi
if [[ "$1" =~ $ra || "${@: -1}" =~ $ra ]]; then
    [[ "$1" =~ $ra ]] && shift || set -- "${@:1:$#-1}"
fi

[[ $quiet -eq 1 ]] && cmd+=(--quiet --no-warnings)
[[ -n "$outdir" ]] && cmd+=(-P "$outdir")

if [[ -z "$2" && "${1:0:8}" == "https://" ]]; then
    [[ $quiet -eq 1 ]] && echo "Downloading..."
    "${cmd[@]}" "$1"
    exit 0
fi
if [[ "${1:0:8}" != "https://" ]]; then
    declare -a res
    [[ $quiet -eq 1 ]] && echo "Searching..."
    mapfile -t res < <(yt-dlp "ytsearch7:$*" -O "%(id)s|%(title)s - %(uploader)s (%(duration_string)s)")
    for ((i=0; i<${#res[@]}; i++)); do echo "$((i+1)). ${res[i]#*|}"; done
    read -rp "Please pick a number (1-${#res[@]}) or q: " ans
    [[ "${ans/quit/q}" == "q" ]] && exit 0
    [[ $quiet -eq 1 ]] && echo "Downloading..."
    "${cmd[@]}" "https://youtu.be/${res[$((ans-1))]%|*}"
fi
mdtable() {
  cols=$(echo $1 | cut -dx -f1)
  rows=$(echo $1 | cut -dx -f2)
  header=$(for i in $(seq 1 $cols); do printf "| col$i "; done; echo "|")
  divider=$(for i in $(seq 1 $cols); do printf "|------"; done; echo "|")
  row=$(for i in $(seq 1 $cols); do printf "|      "; done; echo "|")
  result="$header\n$divider"
  for r in $(seq 1 $rows); do
    result="$result\n$row"
  done
  echo "$result" 
}

add to your ~/.zshrc or whatever shell you use


input :down_arrow:

mdtable 4x6

output :down_arrow:

| col1 | col2 | col3 | col4 |
|------|-------|-----|-----|
|      |      |      |      |
|      |      |      |      |
|      |      |      |      |
|      |      |      |      |
|      |      |      |      |
|      |      |      |      |



non formmated

col1 col2 col3 col4

add a pipe | $CLIPBOARD at the end to save to clipboard (silently)

ever copied a prompt and the silly $ tripped everything up?


no _prompt_prompt.sh

if first character is a $ it ditches it

	
	#!/usr/bin/env sh
	# no_dollar.sh — Strip a leading '$' from commands before execution
	# Works with: zsh, bash, and most POSIX-compatible shells
	#
	# INSTALL (pick your shell):
	#   zsh:  echo 'source ~/no_dollar.sh' >> ~/.zshrc  && source ~/.zshrc
	#   bash: echo 'source ~/no_dollar.sh' >> ~/.bashrc && source ~/.bashrc
	#
	# HOW IT WORKS:
	#   Hooks into the shell's pre-execution phase. If the first non-space
	#   character of your command is '$', it's silently stripped and the
	#   rest runs normally.
	#
	#   Example:
	#     $ ls -la        →  runs: ls -la
	#     $git status     →  runs: git status
	#     $ echo "hello"  →  runs: echo "hello"
	
	# ── zsh ──────────────────────────────────────────────────────────────────────
	if [ -n "$ZSH_VERSION" ]; then
	  # zsh exposes the typed command via $BUFFER in preexec hooks.
	  # We use a preexec function to rewrite the command before execution.
	  _no_dollar_preexec() {
	    : # no-op — rewriting happens at read time via zle widget below
	  }
	
	  # Override the accept-line widget so the line is rewritten before execution
	  _no_dollar_accept_line() {
	    local stripped="${BUFFER#"${BUFFER%%[! ]*}"}"  # lstrip spaces
	    if [[ "$stripped" == \$* ]]; then
	      BUFFER="${stripped:1}"                        # drop the '$'
	    fi
	    zle .accept-line                               # call the real accept-line
	  }
	
	  zle -N accept-line _no_dollar_accept_line
	
	# ── bash ─────────────────────────────────────────────────────────────────────
	elif [ -n "$BASH_VERSION" ]; then
	  # bash doesn't have a pre-exec ZLE equivalent, so we wrap the DEBUG trap.
	  # The trick: rewrite $BASH_COMMAND isn't possible, but we CAN use a
	  # function that bash calls via the prompt command to sanitise readline input.
	  #
	  # Approach: override the readline binding for Return so we can preprocess.
	  # Since bash readline is harder to hook cleanly, we use a PROMPT_COMMAND
	  # trick with `history` to detect and warn, combined with a bash function
	  # alias fallback that covers the most common case.
	
	  # Primary method: bind Return to a bash function via readline macro
	  # This covers interactive input in bash 4.0+
	  _no_dollar_run() {
	    local cmd
	    # Read the current readline buffer via builtin
	    cmd="$(history 1 | sed 's/^[[:space:]]*[0-9]*[[:space:]]*//')"
	    local stripped="${cmd#"${cmd%%[! ]*}"}"
	    if [[ "$stripped" == \$* ]]; then
	      local clean="${stripped:1}"
	      # Replace the history entry and re-run
	      history -s "$clean"
	      eval "$clean"
	    fi
	  }
	
	  # Fallback: command_not_found_handle catches `$ git status` style mistakes
	  # where the shell tries to run a command literally named '$'
	  command_not_found_handle() {
	    # Called when the shell can't find a command named e.g. '$'
	    # Reconstruct the rest of the args as the real command
	    if [[ "$1" == '$' ]] && [[ $# -gt 1 ]]; then
	      shift
	      "$@"
	      return $?
	    fi
	    # Default not-found message for everything else
	    echo "bash: $1: command not found" >&2
	    return 127
	  }
	
	  # Also handle: user types `$ ls` → shell tries to exec a binary named `$`
	  # The command_not_found_handle above catches this cleanly in bash 4+.
	  :
	fi
	# ─────────────────────────────────────────────────────────────────────────────


add as plugin and source or just dump it in your ~/.whatevershellyouuserc