You are not logged in.

#3601 2021-08-15 08:17:01

m6x
Member
From: Germany
Registered: 2020-04-01
Posts: 19

Re: Post your handy self made command line utilities

Small bash script to list all drives with their model names and serial numbers, as well as partition info via lsblk, combined in one:

#!/bin/bash
# ~/.local/bin/driveinfo                        -*- coding: utf-8-auto-unix -*-
# Shows useful info about connected block devices/drives
#------------------------------------------------------------------------------

print_deviceinfo() {
  if [ "${#}" -lt 1 ]; then
    echo "${FUNCNAME[0]}() requires 1 argument (/dev block device path)" >&2
    return 1
  fi

  local DEV="$1"

  if [ -b "$DEV" ]; then
    if command -v 'udevadm' >/dev/null 2>&1; then
      #sernum=$(smartctl -a "$DEV" | grep "Serial Number:" | cut -d ":" -f 2 | sed 's/\ //g')
      sernum=$(udevadm info "$DEV" | cut -d " " -f "2-" | awk -F "=" '{ if ($1 == "ID_SERIAL") { print $2; } }')
      echo "$DEV : $sernum"
    else
      echo "${FUNCNAME[0]}(): Error: 'udevadm' command not found!" >&2
      return 1
    fi
  fi

  return 0
}


MAXNUMBER=99

# /dev/nvmeXnY - NVMe SSD drives
for ((x = 0; x <= MAXNUMBER; x++)); do
  for ((y = 0; y <= MAXNUMBER; y++)); do
    print_deviceinfo "/dev/nvme${x}n${y}"
  done
done

# /dev/sdX - SATA/SCSI drives
for x in {{a..z},{a..z}{a..z}}; do
  print_deviceinfo "/dev/sd${x}"
done

# /dev/mmcblkX - SD/MMC cards / eMMC storage devices
for ((x = 0; x <= MAXNUMBER; x++)); do
  print_deviceinfo "/dev/mmcblk${x}"
done

# /dev/srX - optical drives
for ((x = 0; x <= MAXNUMBER; x++)); do
  print_deviceinfo "/dev/sr${x}"
done


# lsblk output
if command -v 'lsblk' >/dev/null 2>&1; then
  echo ''
  lsblk -o NAME,FSTYPE,SIZE,FSAVAIL,TYPE,HOTPLUG,MOUNTPOINT
fi

# blkid output
#if command -v 'blkid' >/dev/null 2>&1; then
#  echo ''
#  blkid
#fi

int pi = 3;

Offline

#3602 2021-08-15 08:21:12

m6x
Member
From: Germany
Registered: 2020-04-01
Posts: 19

Re: Post your handy self made command line utilities

Small sh script to toggle mouse cursor highlighting on/off. Requires https://github.com/swillner/highlight-pointer. Useful for presentations.

#!/bin/sh
# ~/.local/bin/laserpointer.sh                  -*- coding: utf-8-auto-unix -*-
# Toggle script. Requires https://github.com/swillner/highlight-pointer
#------------------------------------------------------------------------------

if pgrep --full highlight-pointer >/dev/null 2>&1; then
  echo "Stopping cursor highlight. To toggle on/off, run this script again."
  killall highlight-pointer >/dev/null 2>&1
else
  echo "Starting cursor highlight. To toggle on/off, run this script again."
  #find-cursor --repeat 0 --follow --distance 0 --line-width 18 --size 18 --color green &
  nohup highlight-pointer -c '#00ff00' -p '#3399ff' -o 0 -r 15 --show-cursor >/dev/null 2>&1 &
fi

int pi = 3;

Offline

#3603 2021-08-22 00:59:44

quequotion
Member
From: Oita, Japan
Registered: 2013-07-29
Posts: 813
Website

Re: Post your handy self made command line utilities

Back in the day, network devices would have names like eth0 and wlan0, but that was apparently a problem, so they started having "reliable" names like "enp12s0" and "wlp14s0", but sometimes those names change too. I tried setting udev rules to manually name the devices, but that doesn't work, so the only thing left to do to ''reliably'' match a network device with a name that cannot be entirely known is to match by something that can: its mac address. To that end, I came up with this script (and call it from a systemd service at boot to connect my wifi):

#!/bin/bash
iw $(for mac in /sys/class/net/wlp*/address; do [[ $(cat $mac) == "$1" ]] && printf ${mac:15:7}; done) connect "$2"

where $1 is a mac address (ie, "a1:2b:c3:4d:e5:f6") and $2 is an access point

Last edited by quequotion (2021-08-22 01:01:18)

Offline

#3604 2021-08-22 01:04:54

jasonwryan
Anarchist
From: .nz
Registered: 2009-05-09
Posts: 30,424
Website

Re: Post your handy self made command line utilities

Why don't you just put the MACAddress in the file, or use a drop in?
https://wiki.archlinux.org/title/Systemd-networkd#[Match]


Arch + dwm   •   Mercurial repos  •   Surfraw

Registered Linux User #482438

Offline

#3605 2021-08-22 01:30:13

quequotion
Member
From: Oita, Japan
Registered: 2013-07-29
Posts: 813
Website

Re: Post your handy self made command line utilities

jasonwryan wrote:

Why don't you just put the MACAddress in the file, or use a drop in?
https://wiki.archlinux.org/title/Systemd-networkd#[Match]

I am doing that also:

cat /etc/systemd/network/20-wifi.network 
[Match]
MACAddress=a1:2b:c3:4d:e5:f6

[Network]
Address=192.168.0.101
Gateway=192.168.0.1
DNS=127.0.0.1

This does not actually connect the wifi, though, it only ensures a correct ip setup in the local network when it gets connected.

Last edited by quequotion (2021-08-22 01:35:15)

Offline

#3606 2021-08-22 09:18:20

seth
Member
Registered: 2012-09-03
Posts: 49,981

Re: Post your handy self made command line utilities

https://wiki.archlinux.org/title/Networ … face_names
The "reliable" names are simply the wrong choice for 99.8% of users who have one wired and maybe one wifi NIC.

Offline

#3607 2021-08-22 12:38:36

kokoko3k
Member
Registered: 2008-11-14
Posts: 2,390

Re: Post your handy self made command line utilities

Worth reading thread about network naming rules:
https://bbs.archlinux.org/viewtopic.php?id=245428
I even made an aur package to ensure persistent network names, but in the end it is not that useful.
YMMV.

Last edited by kokoko3k (2021-08-22 12:40:12)


Help me to improve ssh-rdp !
Retroarch User? Try my koko-aio shader !

Offline

#3608 2021-08-31 01:46:53

eric.meehan
Member
Registered: 2020-01-01
Posts: 52

Re: Post your handy self made command line utilities

Girnel: A single-file, searchable journal for git repositories.

I wanted a way to be able to track my research alongside my code changes.  This script appends new journal entries to a hidden .girnel file in the root of a git repository, and later parses that file to create a sqlite database searchable by author, date, time, branch, and commit.

I have the script under source control, so feel free to clone the repository if you would like to track updates.

#!/bin/bash
#
# ========
# GIRNEL
# ========
#
# Eric O Meehan
# 2021-08-26
#
# A simple, searchable journal for git repositories.
#

help()
{
    echo "usage:"
    echo "      grnl <mode> 'input'"
    echo "      modes:"
    echo "          -r      read (uses less to read .girnel)"
    echo "          -w      write (opens vim to compose an entry)"
    echo "          -q      query (opens a sqlite database)"
    echo "      input:"
    echo "          -w and -q accept a quoted argument to be used"
    echo "          as the girnel entry or sqlite query respectively"
}

declare -A PROJECT
GIRNEL=""

git_check()
{
    if [[ $(git status 2> /dev/null) == "" ]]
    then
        echo "girnel requires a git repository"
        exit 1
    fi
}

girnel_check()
{
    if [[ $(ls $GIRNEL 2> /dev/null) == "" ]]
    then
        echo ".girnel missing from project root"
        exit 1
    fi
}

setup()
{
    git_check
    PROJECT=(
        ['author']="$(git config user.name)"
        ['date']="$(date +%F)"
        ['time']="$(date +%H:%M:%S)"
        ['repository']="$(git rev-parse --show-toplevel)"
        ['branch']="$(git status | grep branch | cut -d ' ' -f3)"
        ['commit']="$(git rev-parse --short HEAD)"
    )
    GIRNEL="${PROJECT['repository']}/.girnel"
    girnel_check
}

# Compose an Entry

compose()
{
    touch /tmp/girnel
    vim /tmp/girnel
    ENTRY="$(cat /tmp/girnel)"
    if [[ $ENTRY == "" ]]
    then
        echo "No body written, canceling entry."
        exit 0
    fi
}


write()
{
    ENTRY="$(cat /tmp/girnel)"
    rm /tmp/girnel
    echo "========" >> $GIRNEL
    echo "Author: ${PROJECT['author']}" >> $GIRNEL
    echo "Date: ${PROJECT['date']}" >> $GIRNEL
    echo "Time: ${PROJECT['time']}" >> $GIRNEL
    echo "Branch: ${PROJECT['branch']}" >> $GIRNEL
    echo "Commit: ${PROJECT['commit']}" >> $GIRNEL
    echo "" >> $GIRNEL
    echo "$ENTRY" >> $GIRNEL
    echo "" >> $GIRNEL
    echo "" >> $GIRNEL
}

# Query Previous Entries

DB_SCHEMA="CREATE TABLE entries (
        entry_id INTEGER PRIMARY KEY NOT NULL,
        author TEXT,
        date TEXT,
        time TEXT,
        branch TEXT,
        hash TEXT,
        message TEXT NOT NULL
    );"

declare -A ENTRY=(
    ['author']=""
    ['date']=""
    ['time']=""
    ['branch']=""
    ['commit']=""
    ['message']=""
)

insert()
{
    sqlite3 /tmp/girnel.db "
        INSERT INTO entries (
            author, date, time, branch, hash, message
        ) VALUES (
            \"${ENTRY['author']}\",
            \"${ENTRY['date']}\",
            \"${ENTRY['time']}\",
            \"${ENTRY['branch']}\",
            \"${ENTRY['commit']}\",
            \"${ENTRY['message']}\"
        );"
}

create_db()
{
    touch /tmp/girnel.db
    sqlite3 /tmp/girnel.db "$DB_SCHEMA"

    while IFS='' read -r line || [ -n "${line}" ]
    do
        if [[ $line =~ "========" ]]
        then
            if [[ ${ENTRY['message']} != "" ]]
            then
                insert
                ENTRY=(
                    ['author']=""
                    ['date']=""
                    ['time']=""
                    ['branch']=""
                    ['commit']=""
                    ['message']=""
                )
            fi
        elif [[ $line =~ "Author:" ]]
        then
            ENTRY['author']=$(echo "$line" | cut -d ' ' -f2-)
        elif [[ $line =~ "Date:" ]]
        then
            ENTRY['date']=$(echo "$line" | cut -d ' ' -f2-)
        elif [[ $line =~ "Time:" ]]
        then
            ENTRY['time']=$(echo "$line" | cut -d ' ' -f2-)
        elif [[ $line =~ "Branch:" ]]

        then
            ENTRY['branch']=$(echo "$line" | cut -d ' ' -f2-)
        elif [[ $line =~ "Commit:" ]]
        then
            ENTRY['commit']=$(echo "$line" | cut -d ' ' -f2-)
        elif [[ $line != "" ]]
        then
            if [[ ${ENTRY['message']} == "" ]]
            then
                ENTRY['message']="$line"
            else
                ENTRY['message']="${ENTRY['message']}\n$line"
            fi
        fi
    done < $GIRNEL
    insert
}

query()
{
    create_db
    if [[ $# -ge 1 ]]
    then
        sqlite3 /tmp/girnel.db "$1"
    else
        sqlite3 /tmp/girnel.db
    fi
    if [[ $(ls /tmp/girnel.db 2> /dev/null) != "" ]]
    then
        rm /tmp/girnel.db
    fi
}

main()
{
    declare -A OPTIONS=(
        ['-r']=false
        ['-w']=false
        ['-q']=false
    )

    if [[ $# -eq 0 ]]
    then
        compose
        write
    else
        if [[ "$1" != "-r" && "$1" != "-w" && "$1" != "-q" ]]
        then
            help
        else
            OPTIONS["$1"]=true
        fi
    fi

    if [[ ${OPTIONS['-r']} == "true" ]]
    then
        less $GIRNEL
    elif [[ ${OPTIONS['-w']} == "true" ]]
    then
        if [[ $# -gt 1 ]]
        then
            echo "$2" > /tmp/girnel
            write
        else
            compose
            write
        fi
    elif [[ ${OPTIONS['-q']} == "true" ]]
    then
        if [[ $# -gt 1 ]]
        then
            query "$2"
        else
            query
        fi
    fi
}

setup
main "$@"

Offline

#3609 2021-09-05 16:48:51

Automath
Member
Registered: 2016-05-16
Posts: 115

Re: Post your handy self made command line utilities

This is my demon for keeping track of file attributes:

# Esqueleto de demonio para mantenimiento de atributos extendidos de archivo
##########


#!/bin/bash
getfattr --version||exit
setfattr --version||exit
CONFIG_DIR="/etc/attr.d/monitoring.conf"
cat "$CONFIG_DIR"|
while read config; do
monitoring_directory="$(echo "$config"|cut -d' ' -f1)"
EVENTS="$(echo "$config"|cut -d' ' -f2)"
options="$(echo "$config"|cut -d' ' -f3)"
EVENTS="${EVENTS//,/ }"
options="${options//,/ --}"
echo "$EVENTS"
inotifywait --quiet --monitor --no-dereference --recursive "$monitoring_directory" -- |
while read event; do
#####Definiendo las variable globales
event_dir="$(echo $event|
cut -d' ' -f1)"
event_type="$(echo $event|
cut -d' ' -f2)"
event_file="$(echo $event|
cut -d' ' -f3)"
[[ "$event_dir" == "${event_dir///./}" ]]||
event_type=IGNORE_IT 
echo event = $event_type
echo eventdiff = "${event_dir///./}"
for EVENT_ in $EVENTS; do
if [[ "$EVENT_" == "$event_type" ]]; then
#####Iniciando algunas variables generales: fecha, hora, tamaño, etc

ttime=$(date +%s)
humandate="$(date +%Y-%M-%d' '%H:%m:%S.%N' '%z)"
size=$(wc -c "$event_dir""$event_file"|
cut -d' ' -f1)
echo size before= $size
case $event_type in
            'MODIFY')   ####obteniendo los atributos
                 echo size after= $size
                 watch=3600     #####periodo de latencia entre modificiones para ser considerada como tal
                 sizewatch=350
                 history=$(getfattr -d --only-values -n user.date.modify.history "$event_dir""$event_file"|
                 tail -n1)
                 modifycounter=$(getfattr -d --only-values -n user.modify.counter "$event_dir""$event_file"|
                 tail -n1)
                 humanhistory=$(getfattr -d --only-values -n user.date.modify.history.human "$event_dir""$event_file"|
                 tail -n1)
                 sizehistory=$(getfattr -d --only-values -n user.size.history  "$event_dir""$event_file"|
                 tail -n1)

                 #####Procesando algunos datos
                 lastmodify=$(echo $history|
                 rev|
                 cut -d, -f1|
                 rev)
                 lastsize=$(echo $sizehistory|
                 rev|
                 cut -d, -f1|
                 rev)
                 echo last= $lastmodify
                 echo since last=$elapsed
                 elapsed=$(echo $ttime-0$lastmodify|
                 bc)
                 sizediff=$(echo $size-0$lastsize|
                 bc)
                 sizediff=${sizediff#-}
####                echo                 $ttime-$lastmodify,0 ###se graban cambios cada mas de 1 hora desde el último cambio
                 ######Actualizando las variables
                 modifycounter=$(echo 0$modifycounter+1|bc)
                 #####Se usa el periodo watch para revisar si la modificacion es relevante
                 if [[ $elapsed -gt $watch ]]||[[ sizediff -gt $sizewatch ]]; then 
                 echo doing shit
                 sizehistory="$sizehistory","$size"
                 history=$history,$ttime
                 humanhistory="$humanhistory,$humandate"
                 ########Reformateando variables de valores únicos
                 
                 sizehistory=$(echo "$sizehistory"|
                 tr \, '\n'|
                 uniq|
                 tr '\n' \,)
                 sizehistory="${sizehistory%,}"
                 
                 ####Actualiazando los atributos
                 setfattr --raw -n user.date.modify.history -v "${history#,}" "$event_dir""$event_file"
                 setfattr --raw -n user.date.modify.history.human -v "${humanhistory#,}" "$event_dir""$event_file"
                 setfattr --raw -n user.modify.counter -v $modifycounter "$event_dir""$event_file"
                 setfattr --raw -n user.size.history -v "${sizehistory#,}" "$event_dir""$event_file"
                 fi
                 
                 ;;
          CREATE)
                 Definiendo algunas variables necesarias
                 mime_type=$(file -bi "$event_dir""$event_file")
                 disklabel=$(lsblk $(df  -P ~/media/human_bkp/|tail -n1|cut -d' ' -f1) -o LABEL|
                 tail -n1)
                 diskuuid=$(lsblk $(df  -P ~/media/human_bkp/|tail -n1|cut -d' ' -f1) -o UUID|
                 tail -n1)
                 ######Inicializando los atributos
                 getfattr -n user.date.origin "$event_dir""$event_file"||
                 setfattr -n user.date.origin -v $ttime "$event_dir""$event_file"
                 getfattr -n user.date.origin.human "$event_dir""$event_file"||
                 setfattr -n user.date.origin.human -v "$humandate" "$event_dir""$event_file"
                 getfattr -n user.hostname.origin "$event_dir""$event_file"||
                 setfattr -n user.hostname.origin -v "$HOSTNAME" "$event_dir""$event_file"
                 getfattr -n user.disk.label.origin "$event_dir""$event_file"||
                 setfattr -n user.disk.label.origin -v "$disklabel" "$event_dir""$event_file"
                 getfattr -n user.disk.uuid.origin "$event_dir""$event_file"||
                 setfattr -n user.disk.uuid.origin -v "$diskuuid" "$event_dir""$event_file"
                 getfattr -n user.fullpath.origin "$event_dir""$event_file"||
                 setfattr -n user.fullpath.origin -v "$event_dir""$event_file" "$event_dir""$event_file"
                 getfattr -n user.size.origin "$event_dir""$event_file"||
                 setfattr --raw -n user.size.origin -v $size "$event_dir""$event_file"
                 getfattr -n user.modify.counter "$event_dir""$event_file"||
                 setfattr --raw -n user.modify.counter -v 0 "$event_dir""$event_file"
                 getfattr -n user.mime.type "$event_dir""$event_file"||
                 setfattr --raw -n user.mime.type -v $mime_type "$event_dir""$event_file"

                 ;;

        MOVED_TO)#####Obteniendo algunas variables
                 disklabel=$(lsblk $(df  -P ~/media/human_bkp/|tail -n1|cut -d' ' -f1) -o LABEL|
                 tail -n1)
                 diskuuid=$(lsblk $(df  -P ~/media/human_bkp/|tail -n1|cut -d' ' -f1) -o UUID|
                 tail -n1)

                    #### obteniendo atributos
                 datemoved=$(getfattr -d --only-values -n user.date.moved.history  "$event_dir""$event_file"|
                 tail -n1)
                 humandatemoved=$(getfattr -d --only-values -n user.date.moved.history.human  "$event_dir""$event_file"|
                 tail -n1)
                 path_history=$(getfattr -d --only-values -n user.fullpath.history  "$event_dir""$event_file"|
                 tail -n1)
                 moved_history=$(getfattr -d --only-values -n user.moved.fullpath.history  "$event_dir""$event_file"|
                 tail -n1)
                 host_history=$(getfattr -d --only-values -n user.hostname.history  "$event_dir""$event_file"|
                 tail -n1)
                 disklabel_history=$(getfattr -d --only-values -n user.disk.label.history  "$event_dir""$event_file"|
                 tail -n1)
                 diskuuid_history=$(getfattr -d --only-values -n user.disk.uuid.history  "$event_dir""$event_file"|
                 tail -n1)
                 host_movedhistory=$(getfattr -d --only-values -n user.moved.hostname.history  "$event_dir""$event_file"|
                 tail -n1)
                 moved_counter=$(getfattr -d --only-values -n user.moved.counter  "$event_dir""$event_file"|
                 tail -n1)
                    ##### Redefiniendo variables
                 datemoved=$datemoved,$ttime
                 humandatemoved="$humandatemoved","$humandate"
                 path_history="$path_history","$event_dir""$event_file" 
                 moved_history="$moved_history","$event_dir""$event_file" 
                 host_history=$host_hisory,"$HOSTNAME"
                 disklabel_history=$disklabel_hisory,"$disklabel"
                 diskuuid_history=$diskuuid_hisory,"$diskuuid"
                 host_movedhistory=$host_movedhisory,$HOSTNAME
                 moved_counter=$(echo 0$moved_counter+1|bc)
                  ###Formateando algunas variables
                 host_history=$(echo $host_history|###### Eliminando valores contiguos.
                 tr \, '\n'|
                 uniq|
                 tr '\n' \,)
                 host_history=${host_history%,}
                 disklabel_history=$(echo $disklabel_history|###### Eliminando valores contiguos.
                 tr \, '\n'|
                 uniq|
                 tr '\n' \,)
                 disklabel_history=${diskuuid_history%,}
                 diskuuid_history=$(echo $diskuuid_history|###### Eliminando valores contiguos.
                 tr \, '\n'|
                 uniq|
                 tr '\n' \,)
                 diskuuid_history=${diskuuid_history%,}
                 host_movedhistory=$(echo $host_movedhistory|
                 tr \, '\n'|
                 uniq|
                 tr '\n' \,)
                 host_movedhistory=${host_movedhistory%,}
                 #####Aplicando atributos
                 setfattr -n user.date.moved.history -v "${datemoved#,}" "$event_dir""$event_file"
                 setfattr -n user.date.moved.history.human -v "${humandatemoved#,}" "$event_dir""$event_file"
                 setfattr -n user.fullpath.history -v "${path_history#,}" "$event_dir""$event_file"
                 setfattr -n user.moved.fullpath.history -v "${moved_history#,}" "$event_dir""$event_file"
                 setfattr -n user.hostaname.history -v "${host_history#,}" "$event_dir""$event_file"
                 setfattr -n user.disk.label.history -v "${disklabel_history#,}" "$event_dir""$event_file"
                 setfattr -n user.disk.uuid.history -v "${diskuuid_history#,}" "$event_dir""$event_file"
                 setfattr -n user.moved.hostaname.history -v "${host_movedhistory#,}" "$event_dir""$event_file"
                 setfattr -n user.moved.counter -v "$moved_counter" "$event_dir""$event_file"
                 ;;
        _ACCESS)   #### obteniendo atributos #El puto sitema operativo no se entera de nada
                   #### hay que interpretar patrones de eventos para que esto funcione como se debe
                   #### no digas que no lo sabías
                 datecopied=$(getfattr -d --only-values -n user.date.copied.history  "$event_dir""$event_file"|
                 tail -n1)
                 humandatecopied=$(getfattr -d --only-values -n user.date.copied.history.human  "$event_dir""$event_file"|
                 tail -n1)
                 path_history=$(getfattr -d --only-values -n user.fullpath.history  "$event_dir""$event_file"|
                 tail -n1)
                 copied_history=$(getfattr -d --only-values -n user.copied.fullpath.history  "$event_dir""$event_file"|
                 tail -n1)
                 host_history=$(getfattr -d --only-values -n user.hostname.history  "$event_dir""$event_file"|
                 tail -n1)
                 host_copiedhistory=$(getfattr -d --only-values -n user.copied.hostname.history  "$event_dir""$event_file"|
                 tail -n1)
                 copied_counter=$(getfattr -d --only-values -n user.copied.counter  "$event_dir""$event_file"|
                 tail -n1)
                    ##### Redefiniendo variables
                 datecopied=$datecopied,$ttime
                 humandatecopied="$humandatecopied","$humandate"
                 path_history="$path_history","$event_dir""$event_file" 
                 copied_history="$copied_history","$event_dir""$event_file" 
                 host_history=$host_hisory,"$HOSTNAME"
                 host_copiedhistory=$host_copiedhisory,$HOSTNAME
                 copied_counter=$(echo 0$copied_counter+1|bc)
                  ###Formateando algunas variables
                 host_history=$(echo $host_history|###### Eliminando valores contiguos.
                 tr \, '\n'|
                 uniq|
                 tr '\n' \,)
                 host_history=${host_history%,}
                 host_copiedhistory=$(echo $host_copiedhistory|
                 tr \, '\n'|
                 uniq|
                 tr '\n' \,)
                 host_copiedhistory=${host_movedhistory%,}
                 #####Aplicando atributos
                 setfattr -n user.date.copied.history -v "${datecopied#,}" "$event_dir""$event_file"
                 setfattr -n user.date.copied.history.human -v "${humandatecopied#,}" "$event_dir""$event_file"
                 setfattr -n user.fullpath.history -v "${path_history#,}" "$event_dir""$event_file"
                 setfattr -n user.copied.fullpath.history -v "${copied_history#,}" "$event_dir""$event_file"
                 setfattr -n user.hostaname.history -v "${host_history#,}" "$event_dir""$event_file"
                 setfattr -n user.copied.hostaname.history -v "${host_copiedhistory#,}" "$event_dir""$event_file"
                 setfattr -n user.copied.counter -v "$copied_counter" "$event_dir""$event_file"
                 ;;
esac
fi
done
done
done

config file:

/home/human/ CREATE,MODIFY,MOVED_TO,COPIED_TO exclude=/home/human/cdrom/useless/'\.*'

And I think that every modern system should implement something like this as an integrated option.

Offline

#3610 2021-09-07 11:29:03

Awebb
Member
Registered: 2010-05-06
Posts: 6,273

Re: Post your handy self made command line utilities

Storing CD-ROM images for video game emulation can eat nasty amounts of storage space. Fortunately, both PS1 and PS2 emulators support compressed images nowadays. The mame project has come up with a format they call "Compressed Hunks of Data", short chd. There is a chdman utility in mame-tools, that allows converting bin/cue image combos to chd files with great compression ratios. I started compressing my entire Playstation 1 library, but I forgot to somehow log the compression ratios per image, so I needed a tool, that adds the sizes of all the .bin files belonging to a cue file together and compares it with the .chd file.

#!/bin/bash
cuename="$1"
bindir=$(dirname "$1")
chdname=${cuename/cue/chd}
chdsize=$(stat -c %s "$chdname")
totalsize=0

rawout() {
IFS=$'\n'
for i in $(grep -o "\".*.bin\"" "$cuename" | sed s/\"/\/g);do
        binsize=$(stat -c %s "$bindir/$i")
        echo "$i|$(($binsize/1048576))|MiB"
        totalsize=$(expr $binsize + $totalsize)
done
unset IFS

ratio=$(bc<<<"scale=2; $chdsize/$totalsize")

echo "$(basename "$cuename")|$(($totalsize/1048576))|MiB|(total)"
echo "$(basename "$chdname")|$(($chdsize/1048576))|MiB|(ratio: $ratio)"
}
rawout | column -t -s "|" -R 2

The output looks like this:

$ chdratio "Big Bass Fishing (USA).cue"
Big Bass Fishing (USA) (Track 01).bin   33  MiB
Big Bass Fishing (USA) (Track 02).bin   11  MiB
Big Bass Fishing (USA) (Track 03).bin   11  MiB
Big Bass Fishing (USA) (Track 04).bin   11  MiB
Big Bass Fishing (USA) (Track 05).bin    9  MiB
Big Bass Fishing (USA) (Track 06).bin    9  MiB
Big Bass Fishing (USA) (Track 07).bin   11  MiB
Big Bass Fishing (USA) (Track 08).bin    9  MiB
Big Bass Fishing (USA) (Track 09).bin   10  MiB
Big Bass Fishing (USA) (Track 10).bin    4  MiB
Big Bass Fishing (USA) (Track 11).bin   11  MiB
Big Bass Fishing (USA) (Track 12).bin   30  MiB
Big Bass Fishing (USA).cue             163  MiB  (total)
Big Bass Fishing (USA).chd              74  MiB  (ratio: .45)

It depends on bc, because bash doesn't float.

Online

#3611 2021-09-26 22:06:59

zpg443
Member
Registered: 2016-12-03
Posts: 271

Re: Post your handy self made command line utilities

System upgrade bash script to run reflector, informant and pacdiff when doing system upgrade (pacman and AUR). Also removes orphans:

#!/bin/bash
#
# Runs reflector, informant and pacdiff with system upgrade, and removes orphans
#
# Compare current reflector results with existing mirrorlist, and choose whether to
# update the mirrorlist
#
printf "Review reflector update to the mirror list before system upgrade (pacman and aur).\n"
printf "The most recently synchronized U.S. https mirrors, sorted by highest mirror score, are:\n"
reflector -n 5 -c US --connection-timeout 1 --download-timeout 1 -p "https" --sort score | tee /tmp/ml
printf "\nThe existing /etc/pacman.d/mirrorlist is:\n"
cat /etc/pacman.d/mirrorlist
echo -n "Replace /etc/pacman.d/mirrorlist ([Y]/n)? "
read -r overwrite
if [ "$overwrite" == "${overwrite#[Yn]}" ] 
then
    sudo mv /tmp/ml /etc/pacman.d/mirrorlist
    printf "\n/etc/pacman.d/mirrorlist has been updated."
else
    printf "\nSkipping update of /etc/pacman.d/mirrorlist, and using existing list.\n"
fi
#
printf "\nNow checking for new Arch news.\n"
/usr/bin/informant check
#
# Ugrade system with pacman and aur utilities, then remove orphans and run pacdiff
#
echo -n "Proceed with system upgrade using pacman and aur sync (aurutils) ([Y]/n)? "
read -r proceed
if [ "$proceed" == "${proceed#[Yn]}" ] 
then
    printf "\nNow running pacman -Syu, then aur sync -u\n"
    sudo pacman -Syu
    aur sync -u
    printf "Removing orphans if found...\n"
    sudo pacman -Rns $(pacman -Qtdq)
    printf "\nNow running pacdiff...\n"
    sudo pacdiff
    printf "\nDone!\n"
else
    printf "\nSkipping system upgrade.\n"
fi
$SHELL

Modified following Trilby's comments (#3612).

Last edited by zpg443 (2021-09-27 02:03:25)

Offline

#3612 2021-09-26 22:51:50

Trilby
Inspector Parrot
Registered: 2011-11-29
Posts: 29,444
Website

Re: Post your handy self made command line utilities

"$cmd > file; cat file" can just be "$cmd | tee file", and "cp a b; rm a" should just be "mv a b" - this is particularly helpful if the mv/cp fails: using cp and rm, you'll loose the new mirrorlist content if the copy fails, using mv, it'll still be there if the move fails.  Of course if you are going to stick with the 'rm', there'd be no reason for it to be in both branches of the conditional: pull it out and just run it unconditionally after the if / else blocks.

Last edited by Trilby (2021-09-26 22:52:48)


"UNIX is simple and coherent..." - Dennis Ritchie, "GNU's Not UNIX" -  Richard Stallman

Offline

#3613 2021-09-27 00:18:07

icar
Member
From: Catalunya
Registered: 2020-07-31
Posts: 442

Re: Post your handy self made command line utilities

About tee - This image from Wikipedia enlightened me some time ago. Specially useful if the file can only be written as root.

Last edited by icar (2021-09-27 00:18:51)

Offline

#3614 2021-10-16 02:06:43

jasonwryan
Anarchist
From: .nz
Registered: 2009-05-09
Posts: 30,424
Website

Re: Post your handy self made command line utilities

Yes, I'm too lazy to TAB-complete...

#!/usr/bin/env bash
# play videos

dir=$HOME/Downloads/Videos/TV
IFS=$'\n'

# requires mpv
type mpv > /dev/null 2>&1 || {
  printf "%s\n" "No mpv installed, bailing...";
  exit 1;
}

# build array of candidates
read -r -d '' -a files < \
  <(find "$dir" -maxdepth 2 -type f \( \
  -iname "*$1*" \
  -not -name "*.srt" \) 2>/dev/null)

# check for multiple matches
if (( ${#files[@]} > 1 )); then
  prefix="${files%/*}"
  PS3="Select your video: "
  printf "%s\n" "There are ${#files[@]} matches"
  select vid in "${files[@]##*/}"; do
    files="$vid"
    break
  done
fi

# play it like you mean it
if [[ -n $files && -n $prefix ]]; then
  mpv "$prefix"/"${files}"
elif [[ -n "$files" ]]; then
  mpv "$files"
else
  printf "%s\n" "No matches to play"
fi

# vim:set sw=2 ts=2 et:

Arch + dwm   •   Mercurial repos  •   Surfraw

Registered Linux User #482438

Offline

#3615 2021-10-19 16:53:10

zpg443
Member
Registered: 2016-12-03
Posts: 271

Re: Post your handy self made command line utilities

Kid3-cli and kid3-qt are great utilities for managing music libraries, but they do not provide a utility to build a complete music library database at once. In the kid3-qt GUI, there is an export utility, but it is GUI and it only exports one folder at a time.

This coding novice built a bash script to try and bridge that gap.

https://github.com/Harpo3/musicbase

It uses the kid3-qt configuration file ($HOME/.config/Kid3/Kid3.conf) to set some albeit arbitrary format codes to establish record values and applies the format using kid3-cli. Obviously, these two programs would be dependencies of this script.

As always, feedback is appreciated. I plan to add user-level ability to set format codes according to need.

#!/bin/bash
set -e
# Help Function                                                    #
############################################################
Help()
{
   # Display Help
   printf  '\n'
   printf  'Musicbase - A kid3-based music library database creation utility.\n\n'
   printf  'syntax: musicbase.sh DIRPATH [-h] [-m MINDEPTH] [-o FILE] [q]\n\n'
   printf  'Generates a music library database using music file tag data and kid3-cli/kid3-qt export tools.\n' 
   printf 'Processes data from music files at the DIRPATH specified. File type is data separated values (DSV)\nwith carat (^) as the delimiter. Database records include the path to each music file.\n\n'
   printf  'Time to complete varies by processor and can take >10 minutes for large libraries. Check\n'
   printf 'output quality more quickly by testing on a subdirectory.\n\n'
   printf  'options:\n'
   printf  ' -h display this help file\n'
   printf  ' -m minimum subdirectory depth from top directory of music library to music files (default: 1)\n'
   printf  ' -o specify output file name and path (default: %s)\n' "\$HOME/.musiclib.dsv"
   printf  ' -q quiet - hide terminal output\n'
   printf  '\n'
}

# Verify user provided required, valid path
if [ -z "$1" ]
  then
    printf  '\nMissing required argument: path to music directory.\n'
    Help
    exit 1
fi
if [ -d  "$1" ]; then
    libpath=$1
    shift
else
    if [ "$1" == "-h" ]; then
        Help
        exit 1
    fi
    printf 'This directory does not exist: '
    printf '%s\n' "$1"    
    exit 1
fi

# Set default variables
dirdepth=1
outpath="$HOME/.musiclib.dsv"
showdisplay=1

# Use getops to set any user-assigned options
while getopts ":hm:o:q" opt; do
  case $opt in
    h) # display Help
      Help
      exit;;
    m)
      dirdepth=$OPTARG
      shift
      ;;
    o)
      outpath=$OPTARG      
      ;;
    q)      
      showdisplay=0 >&2
      ;;
    \?)
      printf 'Invalid option: -%s\n' "$OPTARG"
      exit 1
      ;;
    :)
      printf 'Option -%s requires an argument.\n' "$OPTARG"
      exit 1
      ;;
  esac
done

# Get list of music subdirectories, using first variable $libpath for library folder, e.g. /mnt/vboxfiles/music
find "$libpath" -mindepth "$dirdepth" -type d > "$HOME"/.albumdirs;
if [ $showdisplay == 0 ] 
then
     printf 'Locating all subdirectories under this path...\n' > /dev/null 2>&1
else 
    printf 'Locating all subdirectories under this path...\n'
fi

# Verify kid3-qt 'musicbase' export format exists-> $HOME/.config/Kid3/Kid3.conf
# If exists is false, add export format to $HOME/.config/Kid3/Kid3.conf; otherwise skip and proceed
kid3confpath=$"$HOME/.config/Kid3/Kid3.conf"
if grep -q "musicbase" "$kid3confpath"
then 
    if grep -q "%{catalognumber}^%{artist}^%{grouping}^%{album}^%{albumartist}^%{title}^%{filepath}^%{genre}^%{seconds}000^%{rating}^^%{songs-db_custom2}^%{work}" "$kid3confpath"
    then
        printf ''
    else
       printf 'A kid3-qt export format was found with the musicbase name, but its format is not a match. Delete this format in kid3-qt, then run musicbase again.\n'
       exit               
    fi
else
    if [ $showdisplay == 0 ] 
    then
        printf 'Adding the musicbase export format to kid3-qt configuration.\n' > /dev/null 2>&1
    else 
        printf 'Adding the musicbase export format to kid3-qt configuration.\n'
    fi
    exportformatidx="$(grep -oP '(?<=ExportFormatIdx=)[0-9]+' "$kid3confpath")"
    # add comma and space to end of ExportFormatHeaders string
    sed -in '/^ExportFormatHeaders/ s/$/, /' "$kid3confpath"
    # add count of 1 to existing value of ExportFormatIdx
    (( exportformatidx++ ))
    sed -i '/ExportFormatIdx.*/c\ExportFormatIdx='"$exportformatidx" "$kid3confpath"
    # add comma, space and value 'musicbase' to end of ExportFormatNames string
    sed -in '/^ExportFormatNames/ s/$/, musicbase/' "$kid3confpath"
    # add comma, space and format string to end of ExportFormatTracks string
    sed -in '/^ExportFormatTracks/ s/$/, %{catalognumber}^%{artist}^%{grouping}^%{album}^%{albumartist}^%{title}^%{filepath}^%{genre}^%{seconds}000^%{rating}^^%{songs-db_custom2}^%{work}/' "$kid3confpath"
    # add comma and space to the end of ExportFormatTrailers string
    sed -in '/^ExportFormatTrailers/ s/$/, /' "$kid3confpath"
fi

# Build music library database
if [ $showdisplay == 0 ] 
then
     printf 'Building database. This can take time for kid3-cli to process, especially for large music libraries...\n' > /dev/null 2>&1
else 
    printf 'Building database. This can take time for kid3-cli to process, especially for large music libraries...\n'
fi
# This is for the spinner, to show the program is working
if [ $showdisplay == 1 ]
then
    i=1
    sp="/-\|"
    echo -n ' '
else 
    printf ''
fi
# Add header to the database file
echo  "ID^Artist^IDAlbum^Album^AlbumArtist^SongTitle^SongPath^Genre^SongLength^Rating^LastTimePlayed^Custom2^GroupDesc" > "$outpath"
# Loop through the albumdirs file using kid3-cli to read the tag info and add it to the database file, 
# while running the spinner to show operation
while IFS= read -r line; do   
    kid3-cli -c "export /tmp/musiclib.dsv musicbase '%{catalognumber}^%{artist}^%{grouping}^%{album}^%{albumartist}^%{title}^%{filepath}^%{genre}^%{seconds}000^%{rating}^^%{songs-db_custom2}^%{work}'" "$line"
    cat /tmp/musiclib.dsv >> "$outpath"
    if [ $showdisplay == 0 ] 
    then
        printf '' > /dev/null 2>&1
    else 
        printf '\b%s' "${sp:i++%${#sp}:1}"
    fi
done < "$HOME"/.albumdirs

# Sort library order using file path column, preserving position of header, and replace library file
(head -n 1 "$outpath" && tail -n +2 "$outpath"  | sort -k7 -t '^') > /tmp/musiclib.dsv
cp /tmp/musiclib.dsv "$outpath"
if [ $showdisplay == 0 ] 
then
     printf 'Finished! Output: %s\n\n' > /dev/null 2>&1"$outpath"
else 
    printf 'Finished! Output: %s\n\n' "$outpath"
fi
#EOF

EDIT: "$HOME"/.albumdirs should be changed to /tmp/albumdirs
EDIT: See Github link for changes made since original post.

Last edited by zpg443 (2021-10-19 23:07:07)

Offline

#3616 2021-10-19 17:50:22

qinohe
Member
From: Netherlands
Registered: 2012-06-20
Posts: 1,494

Re: Post your handy self made command line utilities

You can remove '-z "$1"' check

if (( ${#@} > 0 )); then
    while getopts ":hm:o:q" opt; do
        case $opt in
          h)
            Help
            exit 0
            ;;
          *)
            printf '%s\n' "Error: Wrong option. Try '${app_this} -h'."
            exit 1
            ;;
        esac
    done
else
    print_help
    exit 1
fi

The check is the same as 'run_archiso' uses tongue

Same for all the printf in 'Help', useless...

app_this="${0##*/}"
print_help(){
    local usagetext
    IFS='' read -r -d '' usagetext <<EOF || true

Usage: ${app_this} [option]

Options:
    -h     display this help file\n'
    -m     minimum subdirectory depth from top directory of music library to music files (default: 1)
    ......

Description
           Musicbase - A kid3-based music library database creation utility.
           syntax: musicbase.sh DIRPATH [-h] [-m MINDEPTH] [-o FILE] [q]
    .....

EOF
    printf '%s' "${usagetext}"
}

and

printf 'Locating all subdirectories under this path...\n' > /dev/null 2>&1
printf 'Locating all subdirectories under this path...\n'

to

printf '%s\n' "Locating all subdirectories under this path..." > /dev/null 2>&1
printf '%s\n' "Locating all subdirectories under this path..."

Do with it what you like of course;-) but these are things I saw in a glace.
Haven't even looked at the rest of it...

Offline

#3617 2021-10-19 19:00:41

zpg443
Member
Registered: 2016-12-03
Posts: 271

Re: Post your handy self made command line utilities

Yes, the help file was a train wreck! Thanks for the suggestions.

Offline

#3618 2021-10-19 19:10:49

qinohe
Member
From: Netherlands
Registered: 2012-06-20
Posts: 1,494

Re: Post your handy self made command line utilities

zpg443 wrote:

Yes, the help file was a train wreck! Thanks for the suggestions.

smile
You don't actually need the "printf '%s\n'" it's fine to use a newline at the end of your line, unless there's a string in it, but even then a 'printf "Some text"' would mostly be enough, it depends...

Offline

#3619 2021-10-19 19:43:50

Trilby
Inspector Parrot
Registered: 2011-11-29
Posts: 29,444
Website

Re: Post your handy self made command line utilities

Why create a variable from that heredocument just to print it out immediately after, just cat:

cat << 'EOF'
  Help info line one
    Line two indented a bit more
  And more ...
EOF

I've also embedded help info in a top-of-file comment before:

#!/bin/sh
#
#| ProgramName - Description
#| Version 0.0.0
#|
#| Usage: ...
#|
#| Options:
#| ...

help() {
  sed -n 's/^#|//p' "$0";
}

The pipe there is arbitrary, and is just to differentiate help lines from regular comments.  You can use different prefixes in place of the pipe to differentiate help output, version output, etc.

Last edited by Trilby (2021-10-19 19:44:41)


"UNIX is simple and coherent..." - Dennis Ritchie, "GNU's Not UNIX" -  Richard Stallman

Offline

#3620 2021-10-19 20:13:46

qinohe
Member
From: Netherlands
Registered: 2012-06-20
Posts: 1,494

Re: Post your handy self made command line utilities

Trilby wrote:

Why create a variable from that heredocument just to print it out immediately after, just cat:

cat << 'EOF'

Though, I don't disagree;-) 'cat!=POSIX=coreutils' and 'read variable=builtin/POSIX'...

Offline

#3621 2021-10-19 21:18:03

Trilby
Inspector Parrot
Registered: 2011-11-29
Posts: 29,444
Website

Re: Post your handy self made command line utilities

What?  Are you saying 'cat' is not posix?  Wrong.  As for being a builtin, that depends entirely on the shell and is not dictated by a standard.  In fact, in my shell, cat is a builtin ... and coincidentally, your read command does not work the way it is intended.

But as the shebang was bash anyways (and there were other bashisms) then pure POSIX compliance is irrelevant.

Last edited by Trilby (2021-10-19 21:20:23)


"UNIX is simple and coherent..." - Dennis Ritchie, "GNU's Not UNIX" -  Richard Stallman

Offline

#3622 2021-10-19 22:10:53

qinohe
Member
From: Netherlands
Registered: 2012-06-20
Posts: 1,494

Re: Post your handy self made command line utilities

I than stand corrected, I was always assuming the man page should mention if the tool is POSIX.

What's wrong with that read  command? I use it from an Archiso tool 'run_archiso' the '-d' may not be correct I'm actually not sure what it does...
It does correctly show my help files.

Offline

#3623 2021-10-19 22:14:39

seth
Member
Registered: 2012-09-03
Posts: 49,981

Re: Post your handy self made command line utilities

https://man.archlinux.org/man/core/man-pages/read.1p.en
POSIX specifies only "-r" as parameter for read. Everything else is an extension by your shells implmentation (ie. a bashism)

Edit: see "read --help", the "-d" parameter is explained there.

Last edited by seth (2021-10-19 22:15:55)

Offline

#3624 2021-10-19 22:26:40

qinohe
Member
From: Netherlands
Registered: 2012-06-20
Posts: 1,494

Re: Post your handy self made command line utilities

Ah, now it makes sense, thanks seth & Trilby;-)
'-d delim'
BTW. running 'read --help' = 'read: bad option: -h'

Offline

#3625 2021-10-19 22:29:41

seth
Member
Registered: 2012-09-03
Posts: 49,981

Re: Post your handy self made command line utilities

qinohe wrote:

BTW. running 'read --help' = 'read: bad option: -h'

zsh?
'read --help' is a bashist-bashism

Offline

Board footer

Powered by FluxBB