r_bash – Telegram
rgb/hex converter syntax - how does this work?

Hi All.

I'm preparing a wrapper noscript around these snippets I found that convert rgb to hex and hex to rgb. I eventually want to expand it so that it also converts the alpha channel, but I don't quite understand the syntax. Could someone please break down how these following two functions work:

​

hextorgb() {
: "${1/\#/}"
((r = 16#${:0:2}, g = 16#${:2:2}, b = 16#${:4:2}))
printf '%s\n' "rgb($r, $g, $b)"
}

rgb
tohex() {
printf '#%02x%02x%02x\n' "$1" "$2" "$3"
}


Any insights into what is happening here, particularly in hex\
to_rgb(), would be

greatly appreciated. Thanks in advance.

https://redd.it/zqmvz8
@r_bash
Guidance with homework

I am a beginner and would like some help with an exercise:

Generate 100 files containing one random number each. Scan the files and find the 5 files that have the highest numbers and the 5 files that have the lowest numbers. Write the numbers you receive in a "list.txt" file.

I have already completed the beginning of generating the files.

for x in $(seq 1 100)

do

shuf -i 1-1000 -n 1 -o $x.txt

done

I am uncertain of how to sort the 100 files by what's actually written inside each of the files. This is a written example of how I imagined I could do the rest of the exercise, but I don't actually understand how to put it all together:

for x in $(seq 1 5)

do

for x in $(seq 1 100)

do

#find largest number in files out of the directory

#find lowest number in files out of the directory

#move both of the numbers to list.txt

#remove both of the files out of the directory

#repeat the process by moving and removing the files

done

done

Would this work? Do I need to use head and tail to find the needed values? Sorry if this isn't enough info.

https://redd.it/zrg7o2
@r_bash
Dead-simple command-line options for small noscripts. Specify all your options on a SINGLE line. Live option values are available as environment and shell variables.
https://gist.github.com/fareedst/8979cc7bd9c811ecd450b9be6d511cdf

https://redd.it/zrxzmd
@r_bash
remove all files that contain numerical string in filename?

Is there an ideal way to remove all files in a directory that are within a certain numerical range?

I have tried using both find and rm but the issue i run into is that the numbers are seperated by periods in the file name so i can't do something like:

rm {5..2}

I know I can just run multiple commands like:

find -type f -name '.6' -delete

but find this inefficient!

https://redd.it/zskhq6
@r_bash
I don't understand how bash -c and sh -c work in regard to keybinding

Hello everybody, I have a little noscript that I launch from the terminal to close my current Firefox session open my VPN connection, kill ipv6, so it doesn't rat out my real IP and then start a new FF instance in my VPN profile.

I wanted to make my life a little easier and bind the noscript to a key, and I accidentally felt into a rabbit hole.

The problem is that killing off ipv6 requires sudo permission. So after I press the keybinding (let's say super +v) I want to be prompted by a GUI asking me for my sudoer password.

This is my_noscript that I launch from the terminal, and it works fine, after I call it from the command line I get prompted for my password inside the terminal:

\#!/bin/bash

​

>pkill -f firefox
>
>sudo sysctl -w net.ipv6.conf.all.disable_ipv6=1
>
>sudo sysctl -w net.ipv6.conf.default.disable_ipv6=1
>
>sudo sysctl -w net.ipv6.conf.lo.disable_ipv6=1
>
>nmcli con up id " ......"
>
>firefox --detach -P "my_vpn" &
>
>pkill terminator

terminator is my terminal emulator.

I tried to just associate this noscript to a key, but obviously I don't get prompted for my sudoer password. So after a day of searching online, I still can't make it work.

I tried associating the super+v to the following command : sh -c "pkexec new_noscript"

where the new_noscript is:

>\#!/bin/bash
>
>pkill -f firefox
>
>sysctl -w net.ipv6.conf.all.disable_ipv6=1
>
>sysctl -w net.ipv6.conf.default.disable_ipv6=1
>
>sysctl -w net.ipv6.conf.lo.disable_ipv6=1
>
>sudo -u "my_username" nmcli con up id "..."
>
>/usr/bin/firefox --display="127.0.0.1:10.0" -P "my_vpn"

So I get a GUI prompt asking me for my sudoer password, ipv6 is turned off, my VPN is launched (well at first it was complaining about no VPN secrets, which sounded interesting because I kind of like secrets, but in the end I figured it was just a problem that I was launching nmcli through the root account hence the sudo -u to go back to my normal user account), but Firefox won't launch. The noscript works when started from an interactive bash shell but not as a keybinding, so I guess some x11 variable isn't being passed on.

I tried export DISPLAY=localhost:0.0 before the Firefox line, but I'm just guessing here, I don't really understand what is going on. I would also like in the future to make the noscript more robust, by using ufw as a kill switch.

Can somebody please explain why I can't use bash -c "pkexec command" when associating a keybinding, but I can with sh -c. The OS is Linux Mint cinnamon DE (fork of gnome).

And what exactly does the -c option does. I do not understand it. The bash manual starts with it, really depressing stuff. From a historical point, what exactly does that "c" stand for?

https://redd.it/zspdv5
@r_bash
my noscript to preview all images in a directory (any suggestions?)

Hello,

I have this short noscript that can provide a preview of all images in a directory:

#

for file in *

do

if [[ $file =~ \.jpg$|\.jpeg$|\.png$|\.gif$ ]]

then

kitty +kitten icat --align="left" --background="#1e1e2e" --loop="-1" "$file"

echo "$file"

fi

https://redd.it/zsqwei
@r_bash
Two-Way Mapping/Hashing

Hi folks,

I've got a use-case where I'm wanting to take a user input, and map it to a JIRA ticket reference (it looks something like ABC-1 where the number will vary depending on the user input.

This is fine, I've done it with an associative array (i.e. "${myMap[taskA]}" will return, say, ABC-2).

What I also then want to do is take ABC-2 and get back a human-understandable format, i.e. Task A.

I can't think of a way to do a two-way map without just defining a second associative array, which then leaves me with 2 arrays that contain almost the same data, which is less than ideal!

If anyone has any suggestions, I'd very much appreciate it.

https://redd.it/zsq4mv
@r_bash
I need a sanity check on my function to find installed editors.

For my command line tool ([https://github.com/membersincewayback/gen](https://github.com/membersincewayback/gen)) I recently added a check for installed editors when a user doesn't have \`$EDITOR\` defined. It works, but I just want to make sure I'm not missing something obvious:

which_ed() {
while IFS= read -r file; do
case "$file" in
*/emacs) EDITOR="/usr/bin/emacs"; return ;;
*/mc) EDITOR="/usr/bin/mc"; return ;;
*/micro) EDITOR="/usr/bin/micro"; return ;;
*/nano) EDITOR="/usr/bin/nano"; return ;;
*/ne) EDITOR="/usr/bin/ne"; return ;;
*/nvim) EDITOR="/usr/bin/nvim"; return ;;
*/vim) EDITOR="/usr/bin/vim"; return ;;
*/vi) EDITOR="/usr/bin/vi"; return ;;
esac
done < <(find /usr/bin)
}

This should exit the function when it matches, and the \`find\` seems to be alphabetical, so there's likely no point in having every possible editor, only enough to guarantee a match. (this is also why 'ED" isn't included.)

https://redd.it/zt12qi
@r_bash
Can you run multiple tasks concurrently?

New job and I found myself transitioning from Windows/Powershell to RHEL and Bash, so I have some work ahead of me. I'm working on a project where I want to basically have a noscript look for files in a directory and take 6 of them and basically run a command against all six concurrently. The receiving system they are being processed into can scale and I want to be as efficient as possible instead of taking the monolithic approach and doing it one at a time. Is this feasible?

&#x200B;

Side note. I have been having fun learning this. I've done some Linux work but have always been a windows guy career wise. A good friend congratulated me on "finally getting a real job", lol.

https://redd.it/ztlbi3
@r_bash
defaults read macOS Terminal noscript no longer working

I work in English and French and was using the following noscript as an Xbar plugin to return the current global spelling language setting in the menu bar:

defaults read -g NSPreferredSpellServerLanguage

Everything was working fine on my M1 MBA running Ventura 13.0. I recently replaced the MBA with a 14inch MBP running 13.1, and the noscript is no longer working.

Terminal returns the following messages:

The domain/default pair of (kCFPreferencesAnyApplication, NSPreferredSpellServerLanguage) does not exist

Would anyone be able to help me make it work again?

I'm (obviously) not a programmer and have virtually no knowledge of noscripting languages. Thanks a lot.

https://redd.it/ztw5jq
@r_bash
This media is not supported in your browser
VIEW IN TELEGRAM
I wrote a super minimal file manager in BASH v5+ (unplanned Xmas theme)
https://redd.it/zujbuv
@r_bash
How can I have 2 processes write ongoing to a persistent 3rd process without blindly looping read?

This is part of a broader project to reliably capturing continuous terminal mouse input using BASH without blindly looping read as seen below.

# Where am I stuck?

(Context is at the bottom)

I've arrived at a solution (see: codeblock) where I need two instances of read ("READER 1" and "READER 2") to write their input into into a 3rd process "INTERPRETER". How they're situated causes BASH to sequentially switch between which processes is reading from the stdin of the parent process which completely defeats the leakage problem (see: "The Leakage Problem") even if I add a sleep 2 to their loops which is very surprising.

The follow code works for a while but quickly gums up if i'm click-dragging the mouse. The "INTERPRETER" process eventually reads a value of '' (nothing).

When this happens there's no errors but nothing comes through the pipe from there on. I've had "INTERPRETER" delete the pipe and remake it when it receives nothing but that doesn't "unstuck" the "READER" processes and at no point does anything error. I'm lost as to why this is happening.

I'm also open to any way I can have 2 processes write to a persistent 3rd process in any order with a blocking read (doesn't use an idle-inefficient timeout loop). Even if it's just a simple example I can integrate it.

Script at present:

#!/bin/bash

OnExit() {
# Release mouse
printf '\033?1000;1002;1006;1015l'
kill $ReaderPid1
kill $ReaderPid2
kill $InterpreterPid
rm "$FifoPath"
}
trap OnExit EXIT

# Capture mouse
printf '\033[?1000;1002;1006;1015h'

# Create a named pipe for sending strings to the interpreter
FifoPath='./Pipe'"$$"
[[ -p $FifoPath ] || mkfifo "$FifoPath"

{
{
# INTERPRETER
# Read from reader 1 and 2
# In the future this is where escape sequences will be interpreted
while true; do
read -d '' -s < "$FifoPath"
Buffer+="${REPLY@Q}"
printf 'IN < "%q"\n' "$REPLY"
printf '%s' "BUFFER: $Buffer"
done
} &
InterpreterPid=$!

{
# READER 1
# Read stdin from parent alternating with reader 2
while true; do
read -d '' -u 3 -s -n 1
printf 'OUT1 > "%q"\n' "$REPLY"
printf '%s' "$REPLY" >> "$FifoPath"
done
} &
ReaderPid1=$!

{
# READER 2
# Read stdin from parent alternating with reader 1
while true; do
read -d '' -u 3 -s -n 1
printf 'OUT2 > "%q"\n' "$REPLY"
printf '%s' "$REPLY" >> "$FifoPath"
done
} &
ReaderPid2=$!
} 3<&0

sleep 999

If you want to see this leakage in action, delete "READER 2", run the noscript, click-drag the mouse around for while, Ctrl+C and scroll up.

\---------------------------
Optional Reading:

# Why not use a non-blocking pipe?

I have a working proof of concept where "READER 1 and 2" sequentially write to a non-blocking pipe that "READER" reads but that means checking it every 0.1 seconds to see if there's input which is highly inefficient compared to a blocking solution for something that may need to be left open.

# The Leakage Problem

Reading mouse escape sequences in BASH is like trying to drink from a fire hose with a straw. Even if reading stops for just a moment input builds up and can leak into things like terminal echo. A hackie solution is to use `stty -echo` to hide it and a forgiving interpreter but in my test applications i've seen it leak into other things.

# What do I mean by "just a moment"?

There's not enough time to write what's been read into a non-blocking pipe or even a variable before overflow can occur and that's both with reading one character at a time or reading everything for 0.01 seconds. It'll work 99.99% of the time but reading something like a mouse click-drag will cause it to overflow eventually even in the best scenario.

# Why do it in BASH?

It eliminates needing a 2nd language and it's
associated libraries which makes more sense for some projects.

If I can finish this we all get a compact, native, sourceable, FOSS mouse solution for BASH. :)

If you know even 5% of an answer, i'll take that 5%. Thank you in advance for any help. Very stuck :P

https://redd.it/zuo41p
@r_bash
converting hsl to rgb in bash

Hi all, i'm creating a wrapper noscript around converting color codes, but am running into issues calculating hsl to rgb at the moment. it works pretty well, but it is off giving certain values.

for example, if i pass it hsl(350, 100, 50) it returns 255 0 32. instead of 255 0 85
another example: if i pass hsl(320, 79, 80) it returns 245, 163 214 instead of 244 164 217.

The variations are more egregious depending on the example. I have provided my code below, it is based off of other examples I've found in Java and JavaScript, and as far as I can tell is as close as possible.

https://stackoverflow.com/questions/2353211/hsl-to-rgb-color-conversion

Please if you can review the code and tell me what I'm missing! I greatly appreciate any help here. And thank you so much if you do take the time! I always appreciate the insights this community can provide.

huetorgb() {
# p=mid
# q=chroma
# t=hue
p=$1 q=$2 t=$3

if [ $(echo "$t < 0" | bc -l) -eq "1" ]; then
t=$(echo "scale=2; $t + 1" | bc -l)
fi
if [ $(echo "$t > 1" | bc -l) -eq "1" ]; then
t=$(echo "scale=2; $t - 1" | bc -l)
fi

if [ $(echo "$t <= 1 / 6" | bc -l) -eq "1" ]; then
p=$(echo "scale=2; $p + ($q - $p) 6 $t" | bc -l)
echo "$p"
exit 0
elif [ $(echo "$t < 1 / 2" | bc -l) -eq "1" ]; then
p=$q
echo "$p"
exit 0
elif [ $(echo "$t < 2 / 3" | bc -l) -eq "1" ]; then
p=$(echo "scale=2; $p + ($q - $p) (2 / 3 - $t) 6" | bc -l)
echo "$p"
exit 0
fi
echo "$p"
}


hsltorgb() {
local h s l r g b
h=$(echo "scale=4; $1 / 360" | bc -l)
s=$(echo "scale=2; $2 / 100" | bc -l)
l=$(echo "scale=2; $3 / 100" | bc -l)

# color is grey and all three rgb values should be equal to the $l
if [ $s == 0 ]; then
r=$l
g=$l
b=$l
else
local q p
if [ "$l" < .50 ]; then
q=$(echo "scale=2; $l (100 + $s)" | bc -l)
else
q=$(echo "scale=2; $l + $s - $l
$s" | bc -l)
fi
p=$(echo "scale=2; 2 $l - $q" | bc -l)
# values are slightly off here possibly due to bc or awk calculating
# incorrectly
# r=$(hue_to_rgb "$p" "$q" "$(echo "scale=1; $h + 1 / 3" | bc -l)")
r=$(hue_to_rgb "$p" "$q" "$(echo "$h" | awk '{print $1 + (1 / 3)}')")
g=$(hue_to_rgb "$p" "$q" "$h")
b=$(hue_to_rgb "$p" "$q" "$(echo "$h" | awk '{print $1 - (1 / 3)}')")
fi

r="$(printf "%.0f" "$(echo "scale=4; $r
255" | bc -l)")"
g="$(printf "%.0f" "$(echo "scale=4; $g 255" | bc -l)")"
b="$(printf "%.0f" "$(echo "scale=4; $b
255" | bc -l)")"
echo "$r $g $b $a"

}

https://redd.it/zut4nw
@r_bash
why python noscripts don't work in chrontab

Dear Linux community,

## this is a problem that has come back to haunt me and I wanted to know if someone can enlighten me.

#### when I want to run a python noscript in bash, I give the full path to python interpreter and the full path to my python noscript and it works.

#### when I give the same command in chrontab it doesn't work.

#### when I:
- write the command in a bash file,

- save the bash file,

- make the bash file executable,

- and then run the bash file in chrontab it works.

#### this workflow is annoying and hard to maintain,

#### can someone enlighten me on the cause of this problem?

#### does it have something to do with the shebang?

https://redd.it/zuvol8
@r_bash
Trouble making my custom command without getopts

I'm trying to make my own command without using getopts

if "$1" == "add" # make directory
then
if -n "$2"
then
mkdir $2
else
echo "Usage: debug.sh -add -gr -rm --help"
fi
elif "$1" == "gr" # greetings
then
echo "hello world"
elif -f "$1" # cats a file
then
cat $1
elif "$1" == "rm" # removes directory
then
if -n "$2"
then
rm $2
else
echo "Usage: debug.sh -add -gr -rm --help"
fi
elif "$1" == "--help"
then
echo "Usage: debug.sh -add -gr -rm --help"
else
echo "hello world"
fi

As you can see you can cat a file when you run the noscript like this:

./noscript foofile

How can I make it output the "command usage" in case the file doesn't exist?

https://redd.it/zvkgrr
@r_bash
Is this safe?

Hello,

Sorry for the dumb question but I came across a GitHub repo that's supposed to convert .mov to .mp4 files in Nextcloud automatically. I don't understand what the code is doing and was wondering if anyone could explain and see if it's safe to install on my server.

GitHub: [https://github.com/abctaylor/nextcloud-mov-2-mp4](https://github.com/abctaylor/nextcloud-mov-2-mp4)

Code:

#!/usr/bin/env bash


# Variables
root_folder="/mnt/nextcloud/" # Where to scan
installation_path="/var/www/nextcloud/public_html" # Full path where nextcloud is installed, must not end with '/'
old_extension=".mov" # e.g. ".mov"
new_extension=".mp4" # e.g. ".mp4"
safe_mode=true # true = rename file to .mov-old, false = permanently delete old .mov file
ignoregrep="" # Ignore stderr messages from find that match this grep (e.g. 'Permission denied' for some folder name)
instance_id=$(openssl rand -hex 4)
append_extension=-wip-$instance_id

# Find files to convert
files_to_convert=()
while IFS= read -r -d $'\0'; do
original_filename="$REPLY"
temporary_filename="$original_filename$append_extension"
mv "$original_filename" "$temporary_filename"
files_to_convert+=("$temporary_filename")
done < <(find $root_folder -name "*$old_extension" -print0 2> >(grep -v $ignoregrep >&2))


# Get list of folders to update and remove duplicates
folders_to_update=()
for i in "${files_to_convert[@]}"
do
:
printf "Processing $i\n\n"
xpath=${i%/*}
folders_to_update+=("${xpath:${#root_folder}}") # discard everything after root folder (cuts by length of string)
done
eval folders_to_update=($(for i in "${folders_to_update[@]}" ; do echo "\"$i\"" ; done | sort -u))


# Convert it!
for i in "${files_to_convert[@]}"
do
:
ffmpeg -loglevel panic -i "$i" -q:v 0 -q:a 0 "${i::-${#old_extension}-${#append_extension}}$new_extension"
if [ "$safe_mode" = true ]
then
mv "$i" "$i-old"
else
rm "$i"
fi
done


# Update folders
for i in "${folders_to_update[@]}"
do
:
php $installation_path/occ files:scan --path="$i"
done

Thanks in advance!

https://redd.it/zw7b78
@r_bash
Command to open a noscript in a new terminal window

Hey everyone!

I'm fairly new to bash noscripting (currently studying for LPI).

we had an exercise to create two noscripts, one counts to 10K, the other one monitors the first noscript (with ps -aef) and if it's down, re-open it.

I did the second one like this:

*****

declare -i counter

counter=0

while $counter -lt 2 ; do

declare -i lines

lines=$(ps -aef |grep bex3.sh |wc -l)

if test $lines -lt 2; then

faildate=$(date)

<path>/bex3.sh

sleep 1

fi

done

*****

but it starts the noscript in the same terminal. while it's correct in terms of the homework I was wondering how I can write it to open the noscript in a new terminal window.


Thanks for any help :)

https://redd.it/zwjldf
@r_bash
Weird Behavior Running Script From cron

This has had me scratching my head all day. I have a simple noscript that cd's into a directory and uploads files via sftp. If I run it from the shell, everything runs just fine. But when running via cron it uploads some random txt files that don't even exist on the server.

I adding some logging to monitor what exact files get uploaded, and there's no mention of these files, yet every time the noscript runs via cron those random files appear on the remote server.

Here's the noscript:

-d /mnt/folder/ || exit
date >> log.txt
cd /mnt/folder/SFTP/
pwd >> log.txt
ls .txt&&for i in .txt;do gpg -e --sign -r "key" "$i"; echo "encypted $i" >> log.txt;done
ls .txt&&for i in .gpg; do lftp sftp://user@server -e "cd folder;put $i; bye"; echo "sent $i" >> log.txt; done
rm .gpg
mv
.txt Processed/

https://redd.it/zxef46
@r_bash