Useful scripts

I see an AI post on a forums as being the same etiquette as posting a google link. I.e:

https://www.google.com/search?q=scripts

But sometimes (admittedly fairly rarely) that is valid. If its a complex or non-intuitive search, likewise if it is a complex query and it took a while to stage the issue within the LLM context.

People here (myself included) got frustrated by one guy spamming a bunch of reddit links. As always everything is fine in moderation.
 
I disagree, AI has helped me out numerous times. It doesn't always give me the correcr solution but often points me in the correct direction.
You misunderstood.
I did not say, "Don't use AI!"
I said, "Please, stop posting AI generated stuff here in the forums!"
That's quite a difference.
 
Code:
#!/usr/local/bin/bash
# 0-------------------------------------------------------------------------0
# | make_All_ports_dir                                                      |
# | fill directory /usr/ports/All with symlinks to all portdirs             |
# | (so you can find the nvidia-drivers in category x11 and not x11-drivers |
# 0-------------------------------------------------------------------------0
cd /usr/ports
mkdir -p All
ls | while read cat_name
do
  if [ -d "$cat_name" ]
  then
    cd "$cat_name"
    ls | while read port_name
    do
      if [ -d "$port_name" ]
      then
        echo "port: $cat_name/$port_name"
        ln -fs "/usr/ports/$cat_name/$port_name" "/usr/ports/All/$port_name"
      fi
    done
    cd - > /dev/null
  fi
done
 
Script that transparently wraps www/yt-dlp.

Features:
- Console/terminal compatible.
- Downloads subtitles in all available languages.
- Downloads and embeds thumbnail image.
- Creates an "mkv" file, and separate subtitle file(s) if subtitles are available.
- Prioritises best video quality.
- Can use a configuration file to set defaults, some of which can be overridden from the command line.
- Can specify proxy string for authenticating proxy traversal.
- Can specify individual item URL or playlist (useful for seasons) URL.
- Can specify a file with a list of URLs to download (which can be all playlists or all individual items).

Sample configuration file (~/.config/yt-dlp_wrapper/yt-dlp_wrapper.conf):
Code:
    format='bv*+ba/b'
    proxyString='http://user:password@proxy:3128'
    urlList='false'
    playList='--no-playlist'
The above configuration file would set format to prioritise highest video quality, set an authenticating proxy and credentials, the source would not be a file of URLs, and the URL would be a single item and not a playlist.

The script itself (for above configuration file example: yt-dlp_wrapper.sh):
Code:
#!/bin/sh

#-------------------------------------------------------------------------#
# References
#-------------------------------------------------------------------------#
# man sh
# man sysexits
# man test
# read --help
#
# https://stackoverflow.com/questions/592620/how-can-i-check-if-a-program-exists-from-a-bash-script
# - Test if command/programme exists/is installed.
#
# https://www.grymoire.com/Unix/Sh.html#uh-78
# - Iterate lines in file.
# - Which leads to warning: https://www.shellcheck.net/wiki/SC2002 .
#
# https://www.shellcheck.net/wiki/SC2002
# - Finally get "correct" syntax for reading file line by line.
#
# https://unix.stackexchange.com/questions/1763/how-do-i-split-the-0-variable-to-find-directory-and-relative-paths-in-bash
# - Get full path in script invocation ($0).
#
# https://www.grymoire.com/Unix/Sh.html#uh-96
# - Checking for optional arguments.
#
# https://www.grymoire.com/Unix/Sh.html#uh-71
# - $@ versus ${1+$@} .
# **!! First incorrect option terminates processing of command line,
#   what is left becomes parameters.
#-------------------------------------------------------------------------#

#-------------------------------------------------------------------------#
# Contributors
#-------------------------------------------------------------------------#
#-------------------------------------------------------------------------#

#-------------------------------------------------------------------------#
# Dependencies
#-------------------------------------------------------------------------#
# Bourne/POSIX shell, or Bourne/POSIX compatible shell.
# 'yt-dlp' port/package.
#-------------------------------------------------------------------------#

#-------------------------------------------------------------------------#
# Known issues
#-------------------------------------------------------------------------#
# 'yt-dlp' always generates "ERROR: [generic] '' is not a valid URL", but
# continues the download anyway.
#
# Mixing playlist and non playlist URLs in a URL list file may yield
# unpredictable results.
#-------------------------------------------------------------------------#



#-------------------------------------------------------------------------#
# Version history
#-------------------------------------------------------------------------#
version="1.0.0"
# Version 1.0.0:
# - Initial release.
#-------------------------------------------------------------------------#

#-------------------------------------------------------------------------#
# Signal Traps
#-------------------------------------------------------------------------#
cleanup ( )
{
    # cleanup code goes here
    echo "INT or QUIT trap received..."
}

# [Ctrl][c]=SIGINT [Ctrl][\]=SIGQUIT
trap "cleanup" INT QUIT
#-------------------------------------------------------------------------#

#-------------------------------------------------------------------------#
# Functions
#-------------------------------------------------------------------------#
version ( )
{
    printf "%s\nVersion: %s\n" "${scriptNameExt}" "${version}"
    exit 0
}

show_usage ( )
{
    printf "%s\n" "Usage:"
    printf "%s\n" "${scriptNameExt} -v | --version"
    printf "%s\n" "${scriptNameExt} -h | --help"
    printf "%s\n" "${scriptNameExt} [-d|--debug] [--proxy proxy_string | --proxy=proxy_string] [--url_playlist] [--url_list_file] source"
    printf "%s\n" ''
    printf "%s\n" "-v|--version - shows the version and exits"
    printf "%s\n" "-h|--help - shows usage and exits"
    printf "%s\n" "-d|--debug - shows verbose yt-dlp output"
    printf "%s\n" "--url_playlist - indicates source URL (or source URL list file) is a playlist (or file containing playlist URLs)"
    printf "%s\n" "--url_list_file - indicates source URL is a file containing a list of URLs to download, which are playlists if '--url_playlist' is defined"
    printf "\n"
    printf "%s\n" "Where:"
    printf "%s\n" "- proxy_string is the value to set http_proxy to."
    printf "%s\n" "  E.g. http://user:passwd@proxy:3128"
    printf "%s\n" "- source is either a single item URL, a playlist URL, a file of URLs, or a file of playlist URLs depending on whether --url_list_file and/or --url_playlist are specified."
    printf "\n"
    printf "%s\n" "Note:"
    printf "%s\n" "- mixing URLs that are playlists and not playlists in the same URL list file is not defined, behaviour is unpredictable."
    exit 0
}

command_check ( )
{
    # $1 = command to be checked for existence
    # $2 = Action: [ exit (default) | continue ]
    # $3 = Message
    # $4 = Exit code

    commandCheckAction="${2:-exit}"
    commandCheckMessage="${3:-${1} not available.}"
    commandCheckExitCode="${4:-69}" # man sysexits: 69 = service unavailable: seems closest

    if [ "$( command -v "${1}" > /dev/null 2>&1; echo "$?" )" != '0' ]
    then
        if ! [ "${commandCheckAction}" = 'continue' ]
        then
            printf "%s\n" "Error: ${commandCheckMessage}" >&2
            exit "${commandCheckExitCode}"
        else
            printf "%s\n" "Warning: ${commandCheckMessage}"
        fi
    fi
}

get_script_configuration ( )
{
    if [ -f "${scriptName}/${scriptName}.conf" ] # Settings in script/product subdirectory - presupposes run from bin directory
    then
        ⚠         . "${scriptName}/${scriptName}.conf"
    fi
    if [ -f "/etc/${scriptName}/${scriptName}.conf" ] # Linux system wide settings
    then
        ⚠         . "/etc/${scriptName}/${scriptName}.conf"
    fi
    if [ -f "/usr/local/etc/${scriptName}/${scriptName}.conf" ] # FreeBSD system wide settings
    then
        ⚠         . "/usr/local/etc/${scriptName}/${scriptName}.conf"
    fi
    if [ -f "$HOME/${scriptName}/${scriptName}.conf" ] # User settings
    then
        ⚠         . "$HOME/${scriptName}/${scriptName}.conf"
    fi
    if [ -f "$HOME/.config/${scriptName}/${scriptName}.conf" ] # User settings
    then
        ⚠         . "$HOME/.config/${scriptName}/${scriptName}.conf"
    fi
}

set_defaults ()
{
    format="${format:-bv*+ba/b}"
    proxyString=''
    urlList="${urlList:-false}"
    playList="${playList:---no-playlist}"
}

process_cmdline ( )
{
    while :
    do
        case "$1" in
            -d|--debug)
                debugLevel="--verbose"
                ;;
            -h|--help)
                show_usage
                ;;
            -v|--version)
                version
                ;;
            --proxy=*)
                proxyString="${1##--proxy=}";
                ;;
            --proxy)
                processedTokenCount=$((processedTokenCount + 1));
                shift;
                proxyString="${1}";
                ;;
            --url_list_file)
                urlList="true";
                ;;
            --url_playlist)
                playList='';
                ;;
            *)
                # removing '*)' case will require '--' for "pass through" options/parameters to work
                #   BUT: not providing the '--' will never exit option parsing - so DO NOT disable '*)' case!
                break;
                ;;
        esac
        processedTokenCount=$((processedTokenCount + 1));
        shift
    done
}

url_download ()
{
    # $1 = URL to download

    printf "%s\n" "/------------------------------"
    printf "Downloading media link: %s\n" "${1}"
    ${runEnv} yt-dlp "${debugLevel}" --no-overwrites "${playList}" --format "${format}" --remux mkv --write-subs --sub-langs all --embed-thumbnail --embed-metadata --embed-chapters "${1}"
    printf "%s\n" "------------------------------/"
}
#-------------------------------------------------------------------------#


#-------------------------------------------------------------------------#
# Initialisation
#-------------------------------------------------------------------------#
requiredDependencies='yt-dlp' # list of required programmes (exit script if missing)
optionalDependencies='' # list of optional programmes (continue script if missing)
debugLevel=''
runEnv=''
#-------------------------------------------------------------------------#


#-------------------------------------------------------------------------#
# main
#-------------------------------------------------------------------------#
# script name:
scriptNameExt="${0##*/}"

# script name minus extension:
scriptName="${scriptNameExt%.sh}"

# get script/product default options (stored as global variables)
get_script_configuration
set_defaults

# override script/product default configuration with options if specified
processedTokenCount=0
process_cmdline "$@"
shift $((processedTokenCount)) # must remove processed tokens from "$@" outside function

# store download source (file or item)
download_source="${1}"

# Check for required commands/programmes
if [ -n "${optionalDependencies}" ]
then
    for dependency in ${optionalDependencies}
    do
        command_check "${dependency}" 'continue'
    done
fi
if [ -n "${requiredDependencies}" ]
then
    for dependency in ${requiredDependencies}
    do
        command_check "${dependency}" 'exit'
    done
fi

# set proxy URL if specified:
if [ -n "${proxyString}" ]
then
    runEnv="env http_proxy=${proxyString}"
fi

if [ "${urlList}" != "true" ]
then
    # URL is single download (which may be a playlist)
    url_download "${download_source}"
else
    # URL is filename of file containing multiple download URLs (all of which may be a playlist)
    while read -r line;
    do
        url_download "${line}"
    done < "${download_source}"
fi

exit 0
#-------------------------------------------------------------------------
 
Code:
[…] so you can find the nvidia-drivers in category x11 and not x11-drivers […]
You know, if the potential port name can be expressed by a basic regular expression, re_format(7), you can write:​
Bash:
ls -d /usr/ports/*/*nvidia*
Do you still need a directory full of symbolic links?​
Code:
#!/usr/local/bin/bash
You do not appear to use any bash(1)isms, your script does not consider that things may go wrong (⇒ at least use the ‑errexit flag), and the bulk of it – the looping – can be solved with the standardized find(1) utility (albeit -mindepth/‑maxdepth are extensions):​
Bash:
#!/bin/sh -e
mkdir /usr/ports/All
cd    /usr/ports/All

# If the symbolic link name is omitted to `ln(1)`,
# it just uses the target’s pathname’s last component:
# ln -s ../category/name name  =  ln -s ../category/name
find    .. -type d -mindepth 2 -maxdepth 2 -exec ln -fs '{}' ';'

# Remove broken links. Taken from find(1) § Examples.
#
# -L : If symbolic link target exists, return target’s information.
#      This is usually a directory.
#      If the target has been deleted, the link file’s information is used.
#      That means the `-type` predicate is `l`.
#      This assumes that no symbolic link points to another symbolic link.
find -L .  -type l -exec rm -- '{}' '+'
 
You know, if the potential port name can be expressed by a basic regular expression, re_format(7), you can write:​
Bash:
ls -d /usr/ports/*/*nvidia*
Do you still need a directory full of symbolic links?
You do not appear to use any bash(1)isms, your script does not consider that things may go wrong (⇒ at least use the ‑errexit flag), and the bulk of it – the looping – can be solved with the standardized find(1) utility (albeit -mindepth/‑maxdepth are extensions):​
Bash:
#!/bin/sh -e
mkdir /usr/ports/All
cd    /usr/ports/All

# If the symbolic link name is omitted to `ln(1)`,
# it just uses the target’s pathname’s last component:
# ln -s ../category/name name  =  ln -s ../category/name
find    .. -type d -mindepth 2 -maxdepth 2 -exec ln -fs '{}' ';'

# Remove broken links. Taken from find(1) § Examples.
#
# -L : If symbolic link target exists, return target’s information.
#      This is usually a directory.
#      If the target has been deleted, the link file’s information is used.
#      That means the `-type` predicate is `l`.
#      This assumes that no symbolic link points to another symbolic link.
find -L .  -type l -exec rm -- '{}' '+'
Never had any problem with it. This script is very old and it's only goal is to not waste time on determining inconsistent category placement. It's bash for the tab- completion. The only bashism that I notice now and rhen is an error because I changed a running script with an editor. (Only happens if you insert or delete a line) Never found the reason for that. It wants to save memory by not making a runtime copy of itself or do they want a running script to be able to change itself?

There may be many problems with the script in a different situation but I used to spend more time on finetuning scripts than actually using them. Got rid of that habit. This 1 exists and I use it a lot, so it saves time. It has to be run 1 time on a system with a new portstree. This is also a storage speed indication for me.
 
This is a just a little collection of bash aliases to play the lofi girl radio stations on youtube here:- https://www.youtube.com/channel/UCSJ4gkVC6NrvII8umztf0Ow

You need mpv installed. At the shell prompt typing 'lofi' by itself gets you the original 'hip-hop beats' channel; 'lofi-list' lists the available channels, or you can type lofi<TAB> and bash completion will list them.
Just put these in your .bashrc and then run them straight from the command line, with tab completion.

Bash:
#lofi youtube radio channels
alias lofi-list="alias | awk -F= '/lofi/{ print \$1 }' | cut -d ' ' -f 2 | grep -v list | sort"
MPV_NO_VIDEO="mpv --no-video"
alias lofi="$MPV_NO_VIDEO             https://www.youtube.com/watch?v=EWrX250Zhko >/dev/null"
alias lofi-synthwave="$MPV_NO_VIDEO   https://www.youtube.com/watch?v=4xDzrJKXOOY >/dev/null"
alias lofi-bossa="$MPV_NO_VIDEO       https://www.youtube.com/watch?v=56llPN9tS88 >/dev/null"
alias lofi-piano="$MPV_NO_VIDEO       https://www.youtube.com/watch?v=N0snMcR6aaA >/dev/null"
alias lofi-jazz="$MPV_NO_VIDEO        https://www.youtube.com/watch?v=A8jDx9TLMQc >/dev/null"
alias lofi-classical="$MPV_NO_VIDEO   https://www.youtube.com/watch?v=jXAEIWcGXwE >/dev/null"
alias lofi-guitar="$MPV_NO_VIDEO      https://www.youtube.com/watch?v=E_XmwjgRLz8 >/dev/null"
alias lofi-sleep="$MPV_NO_VIDEO       https://www.youtube.com/watch?v=xORCbIptqcc >/dev/null"
#end lofi youtube radio channels

Examples.

$ lofi<TAB>
lofi lofi-guitar lofi-piano
lofi-bossa lofi-jazz lofi-sleep
lofi-classical lofi-list lofi-synthwave

$ lofi-list
lofi
lofi-bossa
lofi-classical
lofi-guitar
lofi-jazz
lofi-piano
lofi-sleep
lofi-synthwave

$ lofi &
$ lofi-synthwave
$ lofi-guitar &
$ lofi-piano

If you run in the foreground you can exit with ctrl-c, in the background use job control to kill the job.
Offline channels fail silently. Occasionally they change a URL or add/remove channels, you can simply update the aliases to match.
 
Sure, you can make it into a script, put the urls in a hash. get the exit code and handle status, factorise it... I'm just lazy.:-) And the nice thing about doing them as aliases is that you don't need to copy script files around, or make sure they are on your execution path. These are sufficiently small that they only make a minor addition to .bashrc. Probably a better way would be to use shell functions and a hash of the unique sections of the urls.
 
They changed the URL, the beats station is back up. I corrected the earlier post. And they added some new ones. Well... it's easy to grab the urls from their yt page and make new aliases.
 
Back
Top