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:
- Connect your phone to the computer and make sure ADB is connected
- Run the script
- Enter the person’s name when asked
- Enter the WiFi MAC address when asked (find it in Settings > About Phone)
- 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 ![]()
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 ![]()
mdtable 4x6
output ![]()
| 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
