Shell scripts for day to day use...


docbroke

Banned
Joined
Feb 21, 2019
Messages
606
Age
42
Location
India
During years of my using Linux, I have collected tiny useful scripts and in last 2 years learned a bit of bash and made few. I guess the same for other Linux terminal users, so it may be good idea to share some useful tiny scripts.

I will begin with my bookmark handler/ url opener script. I keep my bookmarks in a text file, and launch this script which gives a rofi (dmenu clone) menu with all bookmarks and I can do fuzzy selection by typing few words.

However that is not all. I can search on different sites straight from this script using keywords, for example "wiki big bang theory" will search big bang theory on wikipedia or I can type a valid url to open with browser.

To try this script you will need rofi and surfraw installed. There are plenty of keywords to try, you can find them in script after "case" line. For beginners to bash, you will need to save this script as a text file and make it executable ( chmod +x <script_name> ). It will be best if you save the script in your $PATH, ( /usr/local/bin ) I keep all my scripts in $HOME/bin and add that in $PATH from my .bashrc. I hope this thread will be useful to all, and many more useful scripts will be shared.

You can also run <script_name> -h for in-build help.

Bash:
#!/bin/bash

INFO() {
    cat <<EOF>&2
### DEPENDS ON ###
     "surfraw"-for keyword based search, you will need /usr/lib/surfraw in your path, so add below line to your .bashrc (uncommented)
     PATH=/usr/lib/surfraw:${PATH}
     "trans" and "w3m" for language translations, https://github.com/soimort/translate-shell
     "sdcv" for dictionary use
### CONFIGURATION ###
     place your browser in BROWSER=? line
     place your bookmarks text file with 1 url/line, put it in "BOOKMARKS=?" field
     default script uses rofi, to use dmenu uncomment the line starting with dmenu and comment out previous line starting with rofi
### USE ###
     enter text in rofi/dmenu field, it will be matched against bookmarks, <enter> to open selected bookmark
     to search specific sites use keyword as first argument ( like go for google, wi for wikipedia, aw for archwiki etc.) > read the script to find out all keywords
     to find out route from delhi to mumbai with google map, "nav delhi mumbai" or to search a location only use "map <location>"
     if no keyword or url is used, entire argument will be searched with duckduckgo
     to search with input text only (not matching bookmark) use <C-enter> (rofi only)
     to edit selected bookmark use <C-space> (rofi only)
EOF
}

while getopts h: help; do
    case $help in
    h|\?) INFO && exit ;;
esac
done

shopt -s lastpipe

## Add name of your browser here ( not text-browsers )
#BROWSER=qutebrowser

## add your plain text bookmarks here, you can add tag after the bookmark bookmart url e.g., "www.google.co.in search googlesearch", use "link-handler" for adding bookmarks
BOOKMARKS=~/.config/vimb/bookmark
export PATH=${HOME}/bin:${PATH}
export PATH=/usr/lib/surfraw:${PATH}

# use rofi to display bookmarks and select one
rofi -dmenu -i -matchin fuzzy -location 1 -l 10 -width 100 -font "Inconsolata 14" -p $BROWSER < "$BOOKMARKS" | read -a "url"
## use dmenu inplace of rofi
#/usr/bin/dmenu -l 10 -fn "Inconsolata 14" -p $BROWSER: < "$BOOKMARKS" | read -a url

[[ ! $url ]] && exit

duckimage() {
x=$@
$BROWSER "https://duckduckgo.com/?q=${x// /+}&ia=images&iax=1"
}
duckvideo() {
x=$@; $BROWSER "https://duckduckgo.com/?q=${x// /+}&ia=videos&iax=1"
}
DDG() {
x=$@; $BROWSER "https://duckduckgo.com/?q=${x// /+}"
}
MED() {
x=$@; $BROWSER "http://medical-dictionary.thefreedictionary.com/${x// /+}"
}
FLIPKART() {
x=$@; $BROWSER "https://www.flipkart.com/search?q=${x// /+}"
}
NAV() {
$BROWSER "https://maps.google.com/maps?saddr=$1&daddr=$2"
}

case "${url[0]}" in
    *.*|*:*|*/*)            $BROWSER "${url[0]}" ;;
    aw|awiki)   archwiki    -browser=$BROWSER "${url[@]:1}" ;;
    wi|wiki)    wikipedia   -browser=$BROWSER "${url[@]:1}" ;;
    imdb)        imdb        -browser=$BROWSER "${url[@]:1}" ;;
    aur)        aur         -browser=$BROWSER "${url[@]:1}" ;;
    pkg)        archpkg     -browser=$BROWSER "${url[@]:1}" ;;
    ddg|S|dd)    DDG            "${url[@]:1}" ;;
    go|google)  google      -browser=$BROWSER "${url[@]:1}" ;;
    map)        google -m   -browser=$BROWSER "${url[@]:1}" ;;
    nav)        NAV "${url[1]}" "${url[2]}" ;;
#    image)    google -i   -browser=$BROWSER "${url[@]:1}" ;; 
    image)      duckimage   "${url[@]:1}" ;; 
#    video)    google -v   -browser=$BROWSER "${url[@]:1}" ;; 
    video)      duckvideo   "${url[@]:1}" ;;
    news)        google -n   -browser=$BROWSER "${url[@]:1}" ;;    
    yt|youtube)    youtube     -browser=$BROWSER "${url[@]:1}" ;;
    ebay)        ebay        -browser=$BROWSER "${url[@]:1}" ;;
    fk|flipkart) FLIPKART   "${url[@]:1}" ;;
    pubmed)        pubmed      -browser=$BROWSER "${url[@]:1}" ;;
    git|github)    github      -browser=$BROWSER "${url[@]:1}" ;;
## LOCAL DICTIONARIES
## to use def/guj/hin for dictionaries sdcv needs to setup with working dictionaries.  
    eng)        notify-send "$( sdcv --data-dir ~/dic/english/ "${url[@]:1}" )" && exit ;;
    guj)        notify-send "$( sdcv --data-dir ~/dic/gujarati/ "${url[@]:1}" )" && exit ;;
    hin)        notify-send "$( sdcv --data-dir ~/dic/hindi/ "${url[@]:1}" )" && exit ;;
    def)        notify-send "$( sdcv --data-dir ~/dic/extra/ "${url[@]:1}" )" && exit ;;
## ONLINE TRANSLATION
## to use translation "trans" should be in path with w3m installed, translates to english
    trans)      notify-send "$( trans -brief "${url[@]:1}" )" && exit ;;
## translates to gujarati
    trans_gu)      notify-send "$( trans -brief :gu "${url[@]:1}" )" && exit ;;
## online medical dictionary
    med)        MED         "${url[@]:1}" ;;
    *)    if [[ $BROWSER != dillo ]]; then
            duckduckgo -j -browser=$BROWSER "${url[@]}"
        else
            google -browser=$BROWSER "${url[@]}"
        fi ;;
esac
 
Last edited:
Show cpu usage on the keyboard led:
Bash:
#!/bin/bash
while true; do
in=(`cat /proc/stat | grep 'cpu '`)
sleep 2
inp=(`cat /proc/stat | grep 'cpu '`)
full=$((${in[1]}-${inp[1]} + ${in[2]}-${inp[2]} + ${in[3]}-${inp[3]} + ${in[4]}-${inp[4]}))
ins=$((${in[4]}-${inp[4]}))
let "load=(100*($full-$ins)/$full)"
if   [ $load -lt 25 ]; then
    setleds -num -caps -scroll </dev/tty7
elif [ $load -lt 50 ]; then
    setleds +num -caps -scroll </dev/tty7
elif [ $load -lt 75 ]; then
    setleds +num +caps -scroll </dev/tty7
else
    setleds +num +caps +scroll </dev/tty7
fi
done
Quite usefull for when a program goes nuts and you wont normally notice since that multi core beast of yours doest even care if a core is 100% used by a zombie.
Needs to run as root due to /dev/tty access.
Edit: The values where for said multi core beast, corrected.
 
Last edited:
Show cpu usage on the keyboard led:
Bash:
#!/bin/bash
while true; do
in=(`cat /proc/stat | grep 'cpu '`)
sleep 2
inp=(`cat /proc/stat | grep 'cpu '`)
full=$((${in[1]}-${inp[1]} + ${in[2]}-${inp[2]} + ${in[3]}-${inp[3]} + ${in[4]}-${inp[4]}))
ins=$((${in[4]}-${inp[4]}))
let "load=(100*($full-$ins)/$full)"
if   [ $load -lt 25 ]; then
    setleds -num -caps -scroll </dev/tty7
elif [ $load -lt 50 ]; then
    setleds +num -caps -scroll </dev/tty7
elif [ $load -lt 75 ]; then
    setleds +num +caps -scroll </dev/tty7
else
    setleds +num +caps +scroll </dev/tty7
fi
done
Quite usefull for when a program goes nuts and you wont normally notice since that multi core beast of yours doest even care if a core is 100% used by a zombie.
Needs to run as root due to /dev/tty access.
Edit: The values where for said multi core beast, corrected.


:eek: but how do you know your capslock is on! :D
 
Show cpu usage on the keyboard led:
Bash:
Quite usefull for when a program goes nuts and you wont normally notice since that multi core beast of yours doest even care if a core is 100% used by a zombie.
Needs to run as root due to /dev/tty access.
Edit: The values where for said multi core beast, corrected.
"setleds" seem to work only from console, and quite surprising when suddenly commands you type are in capital.
This may work without sudo if you are running this in console in tty7 ( atleast works on my debian setup)
Post automatically merged:

this one is simpler script for downloading videos or playing them in mpv (uses youtube-dl). It allows choosing video/audio format and quality.
Bash:
#!/bin/bash

[[ ! $1 ]] && exit

shopt -s lastpipe

url="$1"
echo "make a choice"
echo "p) play in best quality d) download in best quality c) choose from all available formats g) copy video url"
read -n 1 decision
case $decision in
    p) mpv --no-resume-playback "$url" ;;
    d) youtube-dl "$url" ;;
    c)  youtube-dl -F --no-playlist "$url"
        echo "choose quality (from first column), to merge use x+y"
        read quality
        echo choose "p) play d) download"
        read -n 1 choice
        case $choice in
            p) mpv --ytdl-format="$quality" --no-resume-playback "$url" ;;
            d) youtube-dl -f "$quality"  "$url" ;;
        esac ;;
    g) youtube-dl --get-url "$url" | xclip -i ;;
#       pgrep sway > /dev/null && youtube-dl --get-url "$url" | wl-copy ;;
esac
 
Last edited:
Shorty: Zip every folder in the same place as the script into its own zip file:
Bash:
#! /bin/bash
dir="./"
inhalt=($(ls $dir))
for file in "${inhalt[@]}"; do
name=$file
zip $file.zip $file/*
done
Obviously this sits in my download folder and is clicked after i downed a manga/webcomic so i can open them with comix.
 
I hope this thread will be useful to all, and many more useful scripts will be shared.
What kind of script do you want to see ? I write shell scripts pretty much every days, so I have a huge collection ;)

about your script, I would suggest to use this syntax :
Bash:
BROWSER=${BROWSER:-"qutebrowser"}
BOOKMARKS=${BOOKMARKS:-"~/.config/vimb/bookmark"}
This way, instead of requesting your user to edit your script, tell them to set theses values in their .bashrc file ;)
 
Shorty: Zip every folder in the same place as the script into its own zip file:
Bash:
#! /bin/bash
dir="./"
inhalt=($(ls $dir))
for file in "${inhalt[@]}"; do
name=$file
zip $file.zip $file/*
done
Obviously this sits in my download folder and is clicked after i downed a manga/webcomic so i can open them with comix.
Nice script. I use vifm, as file manager so it is trivial to create zip from any selected folder.

What kind of script do you want to see ? I write shell scripts pretty much every days, so I have a huge collection ;)

about your script, I would suggest to use this syntax :
Bash:
BROWSER=${BROWSER:-"qutebrowser"}
BOOKMARKS=${BOOKMARKS:-"~/.config/vimb/bookmark"}
This way, instead of requesting your user to edit your script, tell them to set theses values in their .bashrc file ;)
Thanks for hint. I am only looking for new ideas, nothing particular.
 
"setleds" seem to work only from console, and quite surprising when suddenly commands you type are in capital.
This may work without sudo if you are running this in console in tty7 ( atleast works on my debian setup)
</dev/tty7 is used to escape the console only limitiation so it can run on X. Nifty trick to know for every commands, eg you can actually type commands in tt1 without actually switching to there for example.
Sedleds only touches the led, capslock should not be triggered at all.
Does anyone remeber the RC car i build that used setleds to controll it? Man that was awesome with the pandora controls and all.
Nice script. I use vifm, as file manager so it is trivial to create zip from any selected folder.
Yea mine can that too, but only does one zip at a time. So when i want a zip for every chapter of a manga that was ongoing since 20 years that means a lot of clicking.
 
</dev/tty7 is used to escape the console only limitiation so it can run on X. Nifty trick to know for every commands, eg you can actually type commands in tt1 without actually switching to there for example.
Sedleds only touches the led, capslock should not be triggered at all.
Does anyone remeber the RC car i build that used setleds to controll it? Man that was awesome with the pandora controls and all.
I use tty1 by default so your script was failing (using tty7) even with sudo, it said permission denied. But after reading your reply I changed it to tty1 and it works with sudo. Before that I thought you might be using this script from console, so I tried setleds in console and it actually changes fonts to capital there in addition to turning the leds.
 
another script to handle lid status, it locks the screen when lid is closed with power supply connected and suspend if lid is closed while running on battery. Useful for the users of minimal window managers.
Bash:
#!/bin/bash

xlock() {
    ( slock && xset dpms 0 0 300 ) &
    xset dpms 0 0 2
    xset dpms force off
}

while true;
do
    if [[ $(< /proc/acpi/button/lid/LID/state) = *closed ]]
    then
        case $(< /sys/class/power_supply/ACAD/online) in
            1)  [[ ! "$(pidof slock)" ]] && xlock ;;
            0)  systemctl suspend && xlock ;;
        esac
    fi
    sleep 5 ;
done
 
Last edited:
My power supply comes in /sys/class/power_supply/AC0/ not .../ACAD but I guess that depends on your exact system's setup.
I guess that is on your archlinux system, as my arch laptop has AC0 but on my debian (from where I posted the script) has ACAD.
 
It is, on my arch laptop. My archlinux desktop doesn't even have anything under /sys/class/powersupply, but I guess this isn't for users of those types of systems ;)
Very surprising since this is part of the mainline kernel since a while. you might need to load the requiered module (intel_powerclamp for intel based system)
 
Here is one :
Bash:
#!/bin/bash

owner=sebt3
prj=${prj:-"hubzilla"}
vers=$(sed 's/,.*//'<.tags)

make_amd64_desc="Build $owner/$prj:amd64-$vers and push"
make_amd64() {
        sudo docker build -t $owner/$prj:amd64-$vers .
        sudo docker push $owner/$prj:amd64-$vers
}

fetch_arm64_desc="Fetch $owner/$prj:arm64-$vers from kube and push to dockerhub"
fetch_arm64() {
        sudo docker pull 192.168.10.200:5000/$prj:latest
        sudo docker tag 192.168.10.200:5000/$prj:latest $owner/$prj:arm64-$vers
        sudo docker push $owner/$prj:arm64-$vers
        sudo docker rmi 192.168.10.200:5000/$prj:latest
}
build_arm_desc="Send Dockerfile to the pi and build $owner/$prj:arm-$vers"
build_arm() {
        ssh pi@pi mkdir -p /tmp/$prj
        scp -r $(dirname $0)/* $(dirname $0)/.tags pi@pi:/tmp/$prj
        ssh pi@pi "cd /tmp/$prj;sudo docker build -t $owner/$prj:arm-$vers ." && \
        ssh pi@pi "sudo docker push $owner/$prj:arm-$vers"
}
fetch_arm_desc="Fetch the $owner/$prj:arm-$vers from dockerhub"
fetch_arm() {
        sudo docker pull $owner/$prj:arm-$vers
}

manifest_vers_desc="Create and push the $owner/$prj:$vers manifest"
manifest_vers() {
        sudo docker manifest create $owner/$prj:$vers $owner/$prj:amd64-$vers $owner/$prj:arm-$vers $owner/$prj:arm64-$vers || sudo docker manifest create $owner/$prj:$vers $owner/$prj:amd64-$vers $owner/$prj:arm-$vers $owner/$prj:arm64-$vers --amend
        sudo docker manifest push $owner/$prj:$vers
}

latest_tag_desc="Tag all 3 images with latest and push"
latest_tag() {
        sudo docker tag $owner/$prj:arm64-$vers $owner/$prj:arm64-latest
        sudo docker tag $owner/$prj:arm-$vers $owner/$prj:arm-latest
        sudo docker tag $owner/$prj:amd64-$vers $owner/$prj:amd64-latest
        sudo docker push $owner/$prj:arm64-latest
        sudo docker push $owner/$prj:arm-latest
        sudo docker push $owner/$prj:amd64-latest
}

manifest_latest_desc="Create and push the $owner/$prj:latest manifest"
manifest_latest() {
        sudo docker manifest create $owner/$prj:latest $owner/$prj:amd64-latest $owner/$prj:arm-latest $owner/$prj:arm64-latest || sudo docker manifest create $owner/$prj:latest $owner/$prj:amd64-latest $owner/$prj:arm-latest $owner/$prj:arm64-latest --amend
        sudo docker manifest push $owner/$prj:latest
}

task() {
        local p=$(awk -v c=$((38-$(echo "$@"|wc -c)/2)) 'BEGIN{for(i=0;i<c;i++) printf "=" }');
        echo "$p $@ $(awk -v c=$((79-$(echo $p|wc -c)-$(echo "$@"|wc -c))) 'BEGIN{for(i=0;i<c;i++) printf "=" }')";
}

help() {
        cat <<ENDH
$0 [ make_amd64 ] [ fetch_arm64 ] [ build_arm ] [ fetch_arm ] [ manifest_vers ] [ latest_tag ] [ manifest_latest ] [ all ]
make_amd64      : $make_amd64_desc
fetch_arm64     : $fetch_arm64_desc
build_arm       : $build_arm_desc
fetch_arm       : $fetch_arm_desc
latest_tag      : $latest_tag_desc
manifest_vers   : $manifest_vers_desc
manifest_latest : $manifest_latest_desc
all             : All the above steps
ENDH
}

script() {
while [ $# -gt 0 ];do
case $1 in
        make_amd64)      task "$make_amd64_desc";       make_amd64      || return 2;;
        build_arm)       task "$build_arm_desc";        build_arm       || return 3;;
        fetch_arm)       task "$fetch_arm_desc";        fetch_arm       || return 4;;
        fetch_arm64)     task "$fetch_arm64_desc";      fetch_arm64     || return 5;;
        latest_tag)      task "$latest_tag_desc";       latest_tag      || return 6;;
        manifest_vers)   task "$manifest_vers_desc";    manifest_vers   || return 7;;
        manifest_latest) task "$manifest_latest_desc";  manifest_latest || return 8;;
        all)             script make_amd64 build_arm fetch_arm fetch_arm64 latest_tag manifest_vers manifest_latest;;
        *)               echo "ERROR: $1 invalid argument";help;return 1;;
esac
shift
done
}
script "$@"
Most my scripts are longer than this one and have technical usage (I have script to setup base image for a number of sbc boards I have)
Lately I tend to use ansible instead of shell script.
I used to have a script to tag mp3 files based on filename, but I cant find it anymore
 
I too can access my raspberry pi using "ssh pi@pi", but it is mainly used like a remote.

This one is pdf management script, ( extract pages, convert multiple jpg to pdf, join pdf files, decrypt pdf ), depends on poppler-utils, imagemagick/graphicsmagick and qpdf
Bash:
#!/bin/bash

echo -n "
choose option
    m) merge pdf files
    e) extract pages from pdf
    p) image to pdf
    d) remove password
    x) exit
#?  "
read ops

case $ops in
    m)  echo "which files to merge?"
    read -a IN
    echo -n "provide name for output file:"
    read OUT
    pdfunite "${IN[@]}" $OUT.pdf
    ;;
    p)  echo "which image files to convert? e.g., *.jpg"
    read -a IN
    echo -n "provide name for output file:"
    read OUT
    convert "${IN[@]}" $OUT.pdf
    ;;
    e)  echo -n "name the pdf file to extract pages from:"
    read IN
    echo -n "first page to extract:"
    read FIRST
    echo -n "last page to extract:"
    read LAST
    echo -n "provide name for output file:"
    read OUT
    pdfseparate -f $FIRST -l $LAST $IN $OUT%d.pdf
    ;;
    d)  echo -n "Which pdf file to decrypt (without .pdf) ?"
        read FILE
        echo -n "Original password ?"
        read PASS
        qpdf --password="$PASS" --decrypt $FILE.pdf $FILE.decrypted.pdf
        ;;
    x)    exit
    ;;
esac
 
I too can access my raspberry pi using "ssh pi@pi", but it is mainly used like a remote.
If you're lazy like me, you can go as far setting this in your "$HOME/.ssh/config"
Code:
Host            pi
    User            pi

and then you can just ssh pi :p
But in my script, I tend to use more portable code. Just like all these sudo docker. The sudo is useless since I'm in the docker group
 
If you're lazy like me, you can go as far setting this in your "$HOME/.ssh/config"
Code:
Host            pi
    User            pi

and then you can just ssh pi :p
But in my script, I tend to use more portable code. Just like all these sudo docker. The sudo is useless since I'm in the docker group
I am even lazier, I have created alias pi=ssh root@pi, so I only has to type 'pi' :p
 
I like Z for Jump list (quickly jump to directories I frequent):
its a bit heavyweight for the Pandora, so there I just use an alias (or browse with tunar and drag and drop the directory to bash).
If you use zshell, instead use this
If you are on Windows, use this
 
Back
Top