Post your handy utility scripts!

True. One of the original ideas behind the eos-update-notifier was to help newcomers (i.e. not knowing how or when to update) keep the system updated, instead of having them run a system without updates for a long time.
Note that originally we had only the offline install…

Naturally, more experienced users don’t need it (and even might be slightly annoyed about it), but in fact I’m letting the eos-update-notifier run on a daily schedule.

Just a matter of taste… :wink:

1 Like

Actually I’m much worse than most experienced users - I have a vertically smooth scrolling list of coming updates on at all times (when an update is pending - which is nearly always), and a count of how many await updated on screen as well. And I STILL have the functions at hand! :grin: (sometimes the scroll is too slow, and it doesn’t tell me if a reboot is coming…)

Maybe you need a wihle loop of:

while true ; do
   yay
done

:wink:

Seriously, your idea of having to know in advance if a reboot is recommended or not is great!

Someone on a tyhread I can’t find now was talking about a problem they had with updating and NOT rebooting when they should… so I thought I should add that in. Turns out I like it!

Now if I could find that thread, I could link in this one for them…

I created this script for use with a systemd user service for accessing a samba share without implementing any system wide changes.

The script - do remember to run chmod +x on the script file


#! /bin/bash
#
# Script for mounting and unmounting a configured samba share
#  Depends on `smbclient` and `gvfs-smb`
#  Customize the variables as needed
#  - Symlinks are located in designated folder (default: $HOME/SMBLinks)
#  - Symlink can be named  (default: $SHARENAME)
#  - Using `-u` argument will unmount and remove the symlink
#    This program is free software: you can redistribute it and/or modify
#    it under the terms of the GNU General Public License as published by
#    the Free Software Foundation, either version 3 of the License, or
#    (at your option) any later version.
#
#    This program is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU General Public License for more details.
#
#    You should have received a copy of the GNU General Public License
#    along with this program.  If not, see <https://www.gnu.org/licenses/>.
#
# @linux-aarhus - root.nix.dk
#

# MODIFY THESE VARIABLES
# your samba server's hostname or IP address
HOST="my-server"

# the share name on the server
SHARENAME="my-share"

# symlink name
LINKNAME="$SHARENAME"

# symlink is placed in this folder
SYMLINKS="$HOME/SMBLinks"

# /END MODIFY

SCRIPTNAME=$(basename "$0")
VERSION="0.2"

# check argument $1
if [[ "$1" == "-u" ]]; then
    # remove symlink
    rm -f "$SYMLINKS/$LINKNAME"
    # unmount share
    gio mount -u "smb://$HOST/$SHARENAME"
    exit
elif [[ $1 != "" ]]; then
    echo ":: $SCRIPTNAME v$VERSION"
    echo "==> invalid argument: $1"
    echo "Usage: "
    echo "  mount SMB : $SCRIPTNAME"
    echo "  umount SMB: $SCRIPTNAME -u"
    exit 1
fi

# mount command
gio mount "smb://$HOST/$SHARENAME"

# easy reference to gio mount point
ENDPOINT=/run/user/$UID/gvfs/''smb-share:server=$HOST,share=$SHARENAME''

# create the subfolder
if ! [ -d "$SYMLINKS" ]; then
    mkdir -p "$SYMLINKS"
fi

# use --force argument to suppress warning if link exist
ln -sf "$ENDPOINT" "$SYMLINKS/$LINKNAME"

:spiral_notepad: Note:

  • The user service is assuming the above script is located in the service folder.
    Adjust naming accordingly.
  • The service file depends on the credentials has been stored in your keyring.
    Open your file manager’s location bar and input
    smb://samba-server/my-share
    
    Then when prompted store your credentials.
    /home/$USER/.config/systemd/user/gio-mount-share.sh
    
[Unit]
Description=GIO mount smb share-name

[Service]
Type=oneshot
ExecStart=/home/%u/.config/systemd/user/gio-mount-share.sh
ExecStop=/home/%u/.config/systemd/user/gio-mount-share.sh -u
RemainAfterExit=true

[Install]
WantedBy=multi-user.target

Here’s a small script I use to transform my totally obsolete Windows Phone into a quality webcam. It should work with any phone really (iOS, Android etc) provided you install an app on the phone which streams video accessible by IP. (I’d search “IP cam” in the app store on the phone)

#!/usr/bin/bash
#group the elevated privileges commands
pkexec bash -c "\
modprobe v4l2loopback devices=1 video_nr=10 card_label='VirtualCam' exclusive_caps=1; \
modprobe snd-aloop index=10 id='VirtualMic'; \
";
#non elevated privileges commands
pacmd 'update-source-proplist alsa_input.platform-snd_aloop.0.analog-stereo device.description="VirtualMic"'
notify-send -t 5000 --icon=camera-video "Virtual Camera" "Camera now streaming" 
ffmpeg -hide_banner -loglevel error -an -probesize 32 -analyzeduration 0 -listen 0 -i http://user:pass@192.168.0.xx:8080/mjpeg -vf format=yuv420p -f v4l2 -vcodec rawvideo /dev/video10  ; notify-send -t 5000 --icon=camera-video "Virtual Camera" "Camera stopped streaming" ;

You’d need to replace http://user:pass@192.168.0.xx:8080/mjpeg with the stream URL provided by the streaming app on your phone. Keep in mind this is not intended to be a secured stream, but if you’re the only one using the network it should be good enough to casually use as a webcam.

The script requires package v4l2loopback-dkms to be installed.

I’m running the script from a launcher in XFCE panel (in non-terminal mode) hence the system notifications to let me know when the streaming is on and off again. (If the streaming fails the last notification is still triggered, letting me know the stream is off).

2 Likes

To cut online video from youtube/vimeo or other sources.

ytdlcut ()
{
ffmpeg -ss "$2" -i "$(youtube-dl -f "bv*[height<=?1440]" -g --youtube-skip-dash-manifest $1)" -t "$3" -c copy "$(echo "$(youtube-dl -e $1)" | sed 's/[^a-zA-Z0-9 ]//g')-cut.mkv"
}

Switched to yt-dlp recently, but hasn’t become muscle memory yet. :smile:

This uses yt-dlp. Takes 3 input arguments. 1st is URL, 2nd start time, 3rd is Duration. Output file is in pwd. Change the script to your liking. :grin:

I started the script to handle the recurring tasks on my server: https://codeberg.org/Tealk/shell-administration-script

This is a little script that scans all the .jpg files from current working directory and then moves “Landscape” (width >= height) to a destination folder. Does this using identify which makes things more efficient if current directory is a network dir ( say gdrive or mega) and destination is local.

#!/bin/bash
for i in *.jpg ; do width="$(identify -format '%w' "$i")" ; height="$(identify -format '%h' "$i")" ; if [[ $width -ge $height ]] ; then mv -v "$i" /home/username/destination/ ; else echo "Not Landscape Orientation" ; fi ; done
1 Like

For sway - Screenshot button with optional delay (requires pysimplegui):

#!/usr/bin/env python

import PySimpleGUI as sg
import time
from datetime import datetime
import os

sg.ChangeLookAndFeel('Dark')

layout = [[sg.Button("Screenshot", button_color=("red", "black"), size=(13, 1), font=("Noto Sans Bold", 11)),
           sg.Text('Delay:'), sg.InputText('0',size=(4,1),font=("Noto Sans Bold", 11))]]

window = sg.Window("Grim-SS", location=(800, 530), alpha_channel=1,
                   keep_on_top=True, no_titlebar=True).Layout(layout).Finalize()

now = datetime.now()
datestr = now.strftime("~/Pictures/grim/%Y%m%dT%H:%M:%S.png")

while True:
    event, values = window.Read()
    
    if event in (None, 'Exit'):
        break

    if event == 'Screenshot':
        window.Hide()
        Ch=int(values[0])
        time.sleep(Ch) 
        os.system("grim " + datestr)
        break
1 Like

Let’s revive this thread, as it was quite handy…

Here is a very simple script that I came up with just a few minutes ago: clipdump.

It’s a clipboard logger.

Say, for example, I want to download a bunch of files and there is no API or bulk download, so I have to do it URL by URL. I usually copy those URLs from a browser and paste them to a text file and then I just wget them in the end. However, that is tedious as I have to switch back and forth between the browser and the text editor.

So I made this:

#!/bin/bash

set -e

xclip -sel c -i < /dev/null
unset DUMP

while true; do
  c="$(xclip -o -sel c)"

  if [ -z "$c" ]; then
    continue
  fi

  FOUND=0

  for line in "${DUMP[@]}"; do
    if [ "$line" == "$c" ]; then
      FOUND=1
      break
    fi
  done

  if [ $FOUND = 0 ]; then
    echo "$c"
    DUMP+=("$c")
  fi

  sleep 0.1
done

This script looks at my clipboard every 0.1 or so seconds, and writes to standard output if it contains something I haven’t yet copied.

So I just run this in a terminal emulator:

clipdump | tee list.txt 

And while the script is running, I switch over to the browser and start copying URLs, one by one, and this script automatically appends them to the file (without duplicates!). When I’m done, I just switch over to the terminal emulator and terminate the script with the interrupt signal. I am left with a file containing a list of URLs to download, which I can then easily wget.

I’m sure there are other uses for a clipboard logger like this.

6 Likes

This sets the colour temperature for redshift using a slider; the temperature sticks until the script is run again. Useful where there is no built-in night light or addon supporting it.

#!/bin/bash
temp=$(yad --title "Redshift" --text "Set the colour temperature" --scale --step=100 --min-value=1000 --max-value=9000)
redshift -m randr -O $temp -P

I made this to update my mirrors and to make a copy of the existing mirror file in the case that something gets borked. its dependent on the package reflector

#!/bin/bash

# Default number of mirrors to include in the list
DEFAULT_NUM_MIRRORS=20

# Define the default location of your mirror list file
MIRROR_LIST_FILE="/etc/pacman.d/mirrorlist"

# Define the backup directory where you want to store the old mirror list file
BACKUP_DIR="$HOME/mirrorlist_backup"

# Define a function to display help information
function show_help() {
  echo "Usage: $0 [OPTIONS]"
  echo "OPTIONS:"
  echo "  -m, --mirror FILE    Path to mirror list file (default: $MIRROR_LIST_FILE)"
  echo "  -n, --number NUMBER  Number of mirrors to include in the list (default: $DEFAULT_NUM_MIRRORS)"
  echo "  -c, --country CODE   Filter mirrors by two-letter country code (e.g., US, GB, CN)"
  echo "  -h, --help           Show help information"
  exit 0
}

# Check if running with root privileges
if [[ $EUID -eq 0 ]]; then
  echo "This script should not be run with sudo. Please run it without sudo and enter your password when prompted."
  exit 1
fi

# Parse command line arguments
while [[ $# -gt 0 ]]; do
  key="$1"
  case $key in
    -m|--mirror)
      MIRROR_LIST_FILE="$2"
      shift 2
      ;;
    -n|--number)
      NUM_MIRRORS="$2"
      shift 2
      ;;
    -c|--country)
      COUNTRY="$2"
      shift 2
      ;;
    -h|--help)
      show_help
      ;;
    *)
      echo "Invalid option: $key"
      show_help
      ;;
  esac
done

# Set the number of mirrors to include in the list
if [[ -z "$NUM_MIRRORS" ]]; then
  NUM_MIRRORS=$DEFAULT_NUM_MIRRORS
fi

# Create the backup directory if it doesn't exist
mkdir -p "$BACKUP_DIR"
echo "Create the backup directory if it doesn't exist: $BACKUP_DIR"

# Create a backup copy of the mirror list file with a timestamp
BACKUP_FILE="$BACKUP_DIR/mirrorlist_$(date +%Y-%m-%d_%H-%M-%S)"
cp "$MIRROR_LIST_FILE" "$BACKUP_FILE"
echo "Created backup of mirror list file: $BACKUP_FILE"

# Use Reflector to generate a new mirror list and save it to the original file location
echo "Updating mirror list with fastest available mirrors..."
if [[ -n "$COUNTRY" ]]; then
  reflector --latest $NUM_MIRRORS --sort rate --country "$COUNTRY" --save "$MIRROR_LIST_FILE"
else
  reflector --latest $NUM_MIRRORS --sort rate --save "$MIRROR_LIST_FILE"
fi

# Confirm that the new mirror list has been generated and saved successfully
echo "Mirror list updated successfully!"

The message will always show positive/successful result, even when the command fails.
You might want to make it showing the actual result, or only failure, or only success.
For success, add && at the end

reflector --latest $NUM_MIRRORS --sort rate --country "$COUNTRY" --save "$MIRROR_LIST_FILE" &&

or for failure, add ||

reflector --latest $NUM_MIRRORS --sort rate --country "$COUNTRY" --save "$MIRROR_LIST_FILE" ||

and change the message to "Failed to save…`

2 Likes

Or add near the beginning of your script:

set -e

It will exit the script whenever a command has a return value different from 0. Of course, you have to make sure this is what you want.

2 Likes

This alias shows the sizes of installed packages:

alias package-sizes="expac -Q '%m/%n' | column -t -s'/' | sort -n"

You can write it into your ~/.bashrc file, then terminal command package-sizes will show package sizes sorted, largest in the end.

Package expac must be installed for it.

How about a bit of humanization? :upside_down_face:

expac -H M -Q '%m/%n' | column -t -s'/' | sort -n

honka_animated-128px-46

3 Likes
expac -H M -Q '%m/%n' | column -t -s'/' | sort -n -r | less
3 Likes

I have made a script to make a sound play when usb device (thumb drive or hard disk) is plugged in or out. for XFCE only, it works on Mate as well but i don’t use that anymore.
It also works on hot plugged hard disks in a hot swap bay.

Pre conditions:
pygame (pygame-git) (i use git version on manjaro as there are fixes not in the standard version, but that may already be the case in eos)
pyudev
A sound theme installed to /usr/share/sounds (i use adapted version of Smooth)
Make sure that sound playback works (not disabled or volume at 0)

the script, save it as “filename”.py

#!/usr/bin/env python
import pyudev
import pygame
pygame.init()

context = pyudev.Context()
monitor = pyudev.Monitor.from_netlink(context)
monitor.filter_by(subsystem='block', device_type='partition')

for device in iter(monitor.poll, None):
    if device.action == 'add':
        if device.subsystem == 'block':
            pygame.mixer.music.load('/usr/share/sounds/Smooth/stereo/device-added.oga')# loading the add ogg/oga file
            pygame.mixer.music.play()# play the loaded file.
    if device.action == 'remove':
        if device.subsystem == 'block':
            pygame.mixer.music.load('/usr/share/sounds/Smooth/stereo/device-removed.oga')# loading the remove ogg/oga file
            pygame.mixer.music.play()# play the loaded file.

Place the script for example in home and give it execute permission

Create a entry in startup applications and use “scriptname.py”(without the quotes) as command (or browse to the script) and save it

Reboot
Plug in a usb drive, it should playback chosen sound (make sure the sound file is there as there isn’t always a standard sound file in every soundtheme)

If it doesn’t work:
Start a terminal
Execute the script: ./scriptname.py and check the terminal output for errors
Plug in a usb thumb drive and check terminal output again for errors

1 Like

This is a script that I use to automatically change my monitor brightness automatically depending of if the sun is up or not. (I like to have some natural light when possible.)

#!/bin/bash

# this is a script to set my external monitor's brightness
# to high (70% is my personal preference) or low (40% is my personal preference)
# automatically according to day/night.
# it uses ddcutil to access the monitor's settings and sunwait to know
# if it's day or night. It expects a file in the following format in
# the .config directory (the values should be according to location)

## ~/.config/brightness-by-daylight.conf
## Setup for brightness-by-daylight.sh
# latitude="0.000000N"
# longitude="0.000000E"
# scriptdir=<location-of-this-script>
# high=70
# low=40

# just run this script one manually to set it up to run perpetually (hopefully) using 'at'
# (some distros don't come with 'at' preinstalled, so you might need to install 'at' and enable the 'atd' service.)

# it might also be a good idea to add '<location-of-this-script> scheduler' to your DE's autostart list, or to '.profile' so that it launches on system login
# (sometimes I forget to turn on the monitor when I start my PC, so this is better than having a crontab)

# avoid running two concurrent processes
[ "${BRTNESSLOCKER}" != "running" ] && exec env BRTNESSLOCKER="running" flock -en "/tmp/brightness-by-daylight.lock" "$0" "$@" || :

# set location of the config file
[ -z "$XDG_CONFIG_HOME" ] && confdir="$HOME/.config" || confdir="$XDG_CONFIG_HOME"

# read from the config file
if [ -f $confdir/brightness-by-daylight.conf ]; then
    source $confdir/brightness-by-daylight.conf
else
    echo "No config file found!"
    echo "It should be located at [config-dir]/brightness-by-daylight.conf"
    exit
fi

# get sun status
sun_status=$(sunwait poll $latitude $longitude)

# check if we want to access the scheduler. If yes, create a schedule using `at`
if [ "$1" == "scheduler" ]; then
    # get the timings for twilight events and current time
    sunrise_time=$(sunwait report 35.221050N 97.445938W | grep "Daylight:" | awk '{print $4}')
    sunset_time=$(sunwait report 35.221050N 97.445938W | grep "Daylight:" | awk '{print $6}')
    now_time=$(date "+%H:%M")

    # try to figure out if it's twilight right now, then need to adjust sun_status
    [ $sunrise_time == $now_time ] && sun_status="DAY"
    [ $sunset_time == $now_time ] && sun_status="NIGHT"

    # figure out the time of the next twilight
    [ $sun_status == "DAY" ] && time_next=$sunset_time || time_next=$sunrise_time

    # query all `at` tasks
    task_list=$(atq | grep $time_next | awk '{print $1}')

    # loop through all `at` entries to see if a task already exists
    flag=true
    for item in $task_list; do
        [ "$(at -c $item | sed 'x;$!d')" == "$scriptdir/brightness-by-daylight.sh scheduler" ] && flag=false
    done

    # create the schedule
    $flag && at -m $time_next <<<"$scriptdir/brightness-by-daylight.sh scheduler"
fi

# do the brightness adjustment using ddcutil
[ $sun_status == "DAY" ] && target=$high || target=$low
ddcutil setvcp 10 $target
echo "Monitor brightness set to $target%, since it's $(echo $sun_status | tr '[:upper:]' '[:lower:]') time"

There are a lot more scripts I use in my GitHub.