r_bash – Telegram
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
How can I make WAIT to run properly in this case?

I'm trying to wait for a couple of processes to finish before executing other commands, including apt update coming next in the queue, as follows:

pop-upgrade release upgrade & # Pop!OS tool checking for own OS updates
PID=$(pidof pop-upgrade)
wait $PID
apt update && apt full-upgrade -y

This *occasionally* returns this output from `apt`:

E: Could not get lock /var/lib/apt/lists/lock. It is held by process 1485 (packagekitd)
E: Unable to lock directory /var/lib/apt/lists/

To circumvent this, I sandwiched another `wait`:

pop-upgrade release upgrade & # Pop!
OS tool checking for own OS updates
PID=$(pidof pop-upgrade)
wait
$PID
PID=$(pidof packagekitd)
wait
$PID
apt update && apt full-upgrade -y

But now wait throws this error message preventing the system update:

wait: pid 1485 (meaning packagekitd) is not a child of this shell

The thing is I'm running these commands from a noscript as sudo. But don't know how to deal with parents and children thingy.

How can I make wait to do its job(s) properly? Or, maybe, how can I know which process(es) prevent apt work as it should?

Thank you!

https://redd.it/zxea6l
@r_bash
How to start with this problem

Hello guys

&#x200B;

So I have these 4 variables:

A=40

B=50

C=60

Z=100

If I would try to calculate/addition Variable A, B, and C together. Which combination would bring me to the nearest Value of Variable Z, without exceeding the value of Variable Z.

So the answer obviously would be A + C.

How would I do this in a bash noscript? I don't even know how to start because I don't understand the algorithm behind. What would you guys call this problem?

Thank you all!

https://redd.it/zxh3a0
@r_bash
Help with Bash Script

Here is what we currently have and the output:

Any advice would be amazing

Script:

u/echo off

if exist membership.txt del membership.txt

dsquery group -name *splk* >groups.txt

::The FOR command is one single line

for /f "tokens=*" %%g in (groups.txt) do u/echo %%g >>membership.txt && echo Members: >>membership.txt && dsget group %%g -members >>membership.txt && echo **************************************** >>membership.txt

Output

"CN=NERP-Splk-Admin,OU=splunk,OU=Security,OU=Group,DC=erp,DC=navy,DC=mil" 

Members: 

"CN=Name,OU=Users,OU=Accounts,DC=erp,DC=navy,DC=mil"

"CN=Name,OU=Users,OU=Accounts,DC=erp,DC=navy,DC=mil"

****************************************

"CN=NERP-SPLK-Citrix,OU=splunk,OU=Security,OU=Group,DC=erp,DC=navy,DC=mil" 

Members: 

"CN=Name,OU=Users,OU=Accounts,DC=erp,DC=navy,DC=mil"

"CN=Name,OU=Users,OU=Accounts,DC=erp,DC=navy,DC=mil"

****************************************

&#x200B;

What we want the output to look like:

"CN=NERP-Splk-Admin,OU=splunk,OU=Security,OU=Group,DC=erp,DC=navy,DC=mil"-"CN=Name,OU=Users,OU=Accounts,DC=erp,DC=navy,DC=mil"

"CN=NERP-Splk-Admin,OU=splunk,OU=Security,OU=Group,DC=erp,DC=navy,DC=mil"-"CN=Name,OU=Users,OU=Accounts,DC=erp,DC=navy,DC=mil"

"CN=NERP-SPLK-Citrix,OU=splunk,OU=Security,OU=Group,DC=erp,DC=navy,DC=mil"-"CN=Name ,OU=Users,OU=Accounts,DC=erp,DC=navy,DC=mil"

"CN=NERP-SPLK-Citrix,OU=splunk,OU=Security,OU=Group,DC=erp,DC=navy,DC=mil"-"CN=Name,OU=Users,OU=Accounts,DC=erp,DC=navy,DC=mil"

Etc.. we want the output on one line

https://redd.it/zxihr6
@r_bash
(noscript request) automate your server to send this message after a successful backup, or after service restart
https://redd.it/zy57yi
@r_bash
Comment-out (prefix with '#') every line in a file that is not already commented-out?

Hi everyone,

I am struggling for a couple of days with this one.
I cannot figure it out by myself and googling for hours on end did not help either.


What I am looking for:
There is a file, test.cfg for example.


It's contents:
lineone
\#linetwo
\#linethree
linefour

I want my noscript to do the following after executing it:
\#lineone
\#linetwo
\#linethree
\#linefour


Does anyone know a solution for this?
Thanks in advance

https://redd.it/zy8ztv
@r_bash
Why I keep getting a nonsense value?

In the following noscript `p` and `q` are at least 2048 bit long numbers, when multiplying both values (`p`\*`q`) the product in this case `n` keeps giving a smaller value than the expected, instead of getting a 4096 bit value it returns a value around 160 bit long.

#!/bin/bash

generate_random() {
hex=$(head -c 256 /dev/urandom | xxd -p -u | tr -d '\n')
bc <<< "ibase=16; $hex"
}

p="$(generate_random | sed -z 's=\\\n==g')"
q="$(generate_random | sed -z 's=\\\n==g')"

n=$((p * q))

echo "$n"

What is causing this? How can I fix it?

https://redd.it/zyb6xv
@r_bash
How can I tell when a forked process finishes?

Im trying to figure out a good and reliable way to fork processes off in a loop but limit the maximum number of "active" forked processes. right now I figure this out by keeping track of the number of started and completed forked processes (which means that every completed forked process needs to be accounted for, or else the count of currently active processes gets off). Currently, I use something like this:

p0=0 # number of started forked processes
p1=0 # number of finished forked processes
maxParallelThreads=$(nproc)

parFunc() {
# some function
sha256sum "$1"
}

# load inputs to parallelize over into array
mapfile -t inArgs < <(find ./ -type f)

for nn in "${inArgs@}"; do
parFunc "$nn" &
((p0++))
(( ( p0 - p1 ) >= maxParallelThreads )) && wait -nf && ((p1++))
done

The problem with this is that p1 (which counts the number of finished forked processes) only gets incremented if the process finishes while the wait -nf call is active. If it finishes in between wait -nf calls it doesnt get counted in p1, which makes (( p0 - p1 )) (which is the count of currently active forked processes) 1 higher than it should be. If you have a bunch of inputs this loop will slowly fork fewer and fewer processes simultaneously until it is only forking one at a time.

Ive tried a number of ways to increment p1 from within the forked process (modifying it normally, exporting it, etc.), but as best as I can tell bash wont allow this. That said, if anyone here knows how you can modify a variable in the parent shell from a forked process please do share.

The only thing Ive tried that seems like it might work is keeping p1 in a file (on a tmpfs), but im concerned about what would happen when multiple forked processes try to modify the file at the same time. I also could probably keep track on the pid's oof the started forked processes, and replace the wait -nf call with one that continually loops through checking that each process pid still exists until one of them doesnt, but that seems like a really inefficient and unsatisfying solution.

Any suggestions on how I might accomplish this? Thanks in advance.

https://redd.it/zypo1c
@r_bash