r_bash – Telegram
Create case statement dynamically

I've been trying to put together a function to access and edit gists using the github gh command. I've succeeded in getting the correct format for the case options but just trying to piece it all together is a bit troublesome.

The code snippet is:

paste <(seq $(gh gist list --limit 15 | wc -l); gh gist list --limit 15 | awk '{ print " gh gist edit "$1 " ;;" }') | pr -2 -t -s")"

This outputs code similar to this:

1) gh gist edit XXXXXXXXXXXXXXXXXXXX ;;

2) gh gist edit XXXXXXXXXXXXXXXXXXXX ;;

3) gh gist edit XXXXXXXXXXXXXXXXXXXX ;;

4) gh gist edit XXXXXXXXXXXXXXXXXXXX ;;

5) gh gist edit XXXXXXXXXXXXXXXXXXXX ;;

6) gh gist edit XXXXXXXXXXXXXXXXXXXX ;;

7) gh gist edit XXXXXXXXXXXXXXXXXXXX ;;

8) gh gist edit XXXXXXXXXXXXXXXXXXXX ;;

9) gh gist edit XXXXXXXXXXXXXXXXXXXX ;;

10) gh gist edit XXXXXXXXXXXXXXXXXXXX ;;

11) gh gist edit XXXXXXXXXXXXXXXXXXXX ;;


I have tried to figure out how to basically inject this code into a case statement. I've found a bit of code that seems like it should accomplish what im looking for but I can't figure out how to get it to run correctly.

The current noscript is:

#!/bin/bash
set -x
paste <(seq $(gh gist list --limit 15 | wc -l); gh gist list --limit 15 | awk '{ print " gh gist edit "$1 " ;; # " $2 }') | pr -2 -t -s")" > .gist.txt
. <( awk -F= 'BEGIN { print "gistlist() {"
print "case \"$choice\" in" }
{ print "$0" }
END { print "esac"
print "}" }' .gist.txt )

clear & paste <(seq $(gh gist list --limit 15 | wc -l); gh gist list --limit 15 | awk '{ print ") gh gist edit "$1 " ;; # " $2 }') | pr -2 -t -s" "
read -p "pick gist to edit: " -r choice
"$gistlist"

What can I change to make this work the right way or what could be a better way to work this. As is It shows up to 15 gists and will change with new gists added/removed. Once we can get that working, I should be able to add the option to use `gh view` and `gh delete` with the selected gist bit one step at a time. Any help is greatly appreciated


* edit

I got a bit closer with:

#!/bin/bash
set -x
paste <(seq $(gh gist list --limit 15 | wc -l); gh gist list --limit 15 | awk '{ print " gh gist edit "$1 " ;; # " $2 }') | pr -2 -t -s")" > .gist.txt
. <( awk -F= 'BEGIN { print "gistlist() {"
print "case \"$choice\" in" }
{ print "$0" }
END { print "esac"
print "}" }' .gist.txt )

# Within your while loop (or wherever else you want):
clear & paste <(seq $(gh gist list --limit 15 | wc -l); gh gist list --limit 15 | awk '{ print ") gh gist edit "$1 " ;; # " $2 }') | pr -2 -t -s" "
read -p "pick gist to edit: " -r choice
#"$gistlist"
paste <(seq $(gh gist list --limit 15 | wc -l); gh gist list --limit 15 | awk '{ print " gh gist edit "$1 " ;; # " $2 }') | pr -2 -t -s")" | awk -F= 'BEGIN { print "case \"$choice\" in" }
{ print $0 }
END { print "esac"}'

https://redd.it/11bpkhv
@r_bash
Why is this only triggering on Saturday and not

This was working on a previous installation of Linux Mint. I have since migrated to MxLinux. So much more lightweight. I transferred some bash noscripts over but now it triggers only on Saturdays a 1600. when before it triggered M-F as expected. I removed everything that is not needed below the time checks as it is not necessary. I have checked my date and time on my OS to ensure it is correct.

The actions under the initial time and date check are performing 7 days a week instead of the days of the week of 1-5 also. ZSH is also needed due to needing some to read decimals which bash cannot correctly complete.

&#x200B;

The end of day notify triggers only on Saturday at 1600. I have changed nothing from one OS to another during the migration.

#!/usr/bin/env zsh
export TERM=xterm-256color
eodnotify=15:59
while true ; do
if [ "$(date +"%T")" > '09:30:00' ] && [ "$(date +"%T")" < '16:00:00' ] && [ "$(date +"%u")" -ge 1 ] && [ "$(date +"%u")" -le 5 ]; then
<actions 1>
if <actions 1 check>; then
<actions>
fi
elif [ "$(date +%H:%M)" == *"$eodnotify"* ];then
<actions>
fi
done

https://redd.it/11bw6vg
@r_bash
Shellcheck says my code is okay when it isn't

Why does shellcheck say the following is okay,

#!/usr/bin/env bash
for drive in /dev/sata[0-9]{1,2}; do echo "$drive"; done

when it does not work as I expected:

# for drive in /dev/sata[0-9]{1,2}; do echo "$drive"; done
/dev/sata[0-9]1
/dev/sata[0-9]2

I've got it working by using:

#!/usr/bin/env bash
for drive in /dev/sata*; do
if [[ $drive =~ /dev/sata[1-9][0-9]?$ ]]; then
echo "$drive"
fi
done

Which returns the names of my 4 sata drives (and excludes the partitions on each drive):

/dev/sata1
/dev/sata2
/dev/sata3
/dev/sata4

But I'm curious why shellcheck led me down a dead end?

https://redd.it/11c2355
@r_bash
How many shell noscripts are supporting your app or mission critical services?

You know: those quick and dirty ones you develop to meet a deadline yet they live on and are impossible to remove?

I ask not only out of curiosity but also to offer some solutions.

https://redd.it/11c3ef0
@r_bash
How can I display a message on terminal in a bash noscript when the user launches ctrl+c on the gnome-terminal in a way that does not interrupt the bash noscript execution?

How can I display a message on terminal in a bash noscript when the user launches ctrl+c on the gnome-terminal in a way that does not interrupt the bash noscript execution? That means the noscript should not come to a halt or change the execution flow or results. Except for the message on terminal, it should just run as if no ctrl+c had been used.

Thanks

https://redd.it/11cbjch
@r_bash
Why is sed not applied to the output in this noscript?

ssh -T root@somehost << EOL
wget https://somesite | tee -a wget.log | sed '/blah/d'
EOL

https://redd.it/11cmm2p
@r_bash
Simple bash TUI toolkit

Providing a clean bash UI sometimes becomes a mess and interactivity is hard to achieve especially when it should be portable.

So I built a tiny library making it a bit easier:
https://github.com/timo-reymann/bash-tui-toolkit

The target is to provide a simple-to-use toolkit that can be dropped into any bash noscript and is compatible no matter the target system.

Works fine on Windows, Linux and MacOS so far :)

https://redd.it/11cwsna
@r_bash
Explanation of sed Command

I was wondering if someone could explain the following sed command:

sed --in-place '/text1/{n; s/text2/text3/}' file.txt

It's supposed to replace text2 with text3 but only if it is on a line following a line that contains text1. I get the /text1/ portion which is supposed to select lines with text1 in them. What I can't seem to find an explanation for is why curly braces are used and what n; inside those braces does to make this command only act on a line that follows a line containing text1.

https://redd.it/11d1k3v
@r_bash
How can i check if a file exists with a certain extension

I need to check if a file exists with a specific extension. Like file.chd specifically. However [ -f $file.chd ] doesn't work for example. There are other files of the same name with a different extension that the -f option picks up instead. How should i do this

https://redd.it/11da7sx
@r_bash
where did I go wrong here in my code?

I took an assesment for a job through HackerRank and got this one wrong and I cant go back and look at the actual assesment anymore but its "GRINDING MY GEARS" like Peter Griffin that I got this wrong.

Problem Statement:

complete function mort_calc given the loan amount annual interest and period of loan years, you need to calculate the monthly payment. the loan amount is principle. the annual interest can be converted into normal percent interest per month

#!/bin/bash

mortgagecalculator() {
principal=$1
annual
interestrate=$2
years=$3

# Calculate the monthly interest rate
monthly
interestrate=$(echo "scale=8; $principal + $annualinterestrate + $years" | bc -l)

# Return the monthly payment
echo "$monthly
payment"
}

# sample input
principal=300000
annualinterestrate=0.0375
years=30

# call the function
monthlypayment=$(echo "$principal + $annualinterestrate + $years" | bc)

result=$(printf "%.2f" $monthly
payment)

# output
echo $result
# output: 1389.23


this code is not outputting what its supposed to be down there at the bottom, I cant find where my calculations went wrong.

Thanx in advance ya'll

https://redd.it/11db80x
@r_bash
help noscript is not functioning properly

So here's some of the function of my setup noscript
#!/usr/bin/env bash
# set -x

base_url="https://raw.githubusercontent.com/lime-desu/dootsfile/main"

declare -A PACKAGE_LISTS=(
["pacman"]="${base_url}/noscripts/install/packages/arch.txt"
["apt"]="${base_url}/noscripts/install/packages/debian.txt"
["dnf"]="${base_url}/noscripts/install/packages/fedora.txt"
["xbps-install"]="${base_url}/noscripts/install/packages/void.txt"
)

install_packages() {
for package_manager in "${!PACKAGE_LISTS[@]}"; do
case "$package_manager" in
dnf|apt) package_manager_command="sudo $package_manager install ";;
pacman|xbps-install) package_manager_command="sudo $package_manager -S";;
*) echo "${BLD}${RED}Error:${RST} Unsupported package manager.";;
esac
readarray -t packages < <(curl -fsSL "${PACKAGE_LISTS[$package_manager]}")
package_list=$(printf '%s ' "${packages[@]}")

eval "${package_manager_command} ${package_list}"
bat cache --build
done
}

install_packages


What it does is fetch the packages list from the remote url on the defined associative array and install it.

Now at first glance the function is really fine. trying it out Yes it works, it does install all of the packages defined on the list.txt (even though already installed).

I decided to do some testing i removed some packages (uninstalled bat btop cava chafa delta exa and neofetch). Now I run again the noscript. All of my removed packages doesn't get installed.

Hmm, that's weird there's something wrong, now I did some debugging

+ eval 'sudo dnf install  alacritty bat btop cava chafa util-linux-user curl git-delta exa fd-find foot thefuck fzf git jq kitty lsd mpv neofetch neovim ripgrep stow starship tar tmux unzip wget wl-clipboard zsh '
++ sudo dnf install alacritty bat btop cava chafa util-linux-user curl git-delta exa fd-find foot thefuck fzf git jq kitty lsd mpv neofetch neovim ripgrep stow starship tar tmux unzip wget wl-clipboard zsh
Last metadata expiration check: 1:26:27 ago on Mon 27 Feb 2023 08:07:52 PM PST.
Package alacritty-0.10.1-3.fc37.x86_64 is already installed.
Package util-linux-user-2.38.1-1.fc37.x86_64 is already installed.
Package curl-7.85.0-6.fc37.x86_64 is already installed.
Package foot-1.13.1-1.fc37.x86_64 is already installed.



As you can see on the log the package that I removed are listed clearly (sudo dnf install ... bat btop cava ... git-delta...) and yet why it doesnt get included on the installation any ideas why?

https://redd.it/11dc4fh
@r_bash
Question About sed c Command?

Does anyone know if you select a range of lines with sed and then use the c command, will it replace each line in the range with the text passed to the c command? In other words, if 10 lines are in the range will there be 10 changes? Or will it replace all 10 lines with just one copy of the text passed to the c command?

https://redd.it/11dit6q
@r_bash
Replace multiple lines with multiple lines?

Given the following input file:

text
text
pattern2
pattern3
text
text
pattern1
pattern2
pattern3
pattern2
pattern3
pattern2
pattern3
text
text

I need to search for "pattern1" and then I need to replace the first occurrence of "pattern2" and "pattern3" with "newpattern2" and "newpattern3" respectively and delete all other occurrences of "pattern2" and "pattern3". The end result I'm after is:

text
text
pattern2
pattern3
text
text
pattern1
newpattern2
newpattern3
text
text

At first I thought I could do this with sed by selecting a range of lines starting with "pattern1" and ending with "pattern3" and then using the c command to replace the whole range but range selecting in sed is non greedy so that won't work. However, I could still use sed to do the replacement but then need to figure out another way to delete all other occurances of "pattern2" and "pattern3" that come after "pattern1".

This is running in a busybox environment so no access to perl or most other fancy tools. Basically sed, awk, and grep are the only file/string manipulation tools I can think of that busybox supports.

https://redd.it/11dl5y0
@r_bash
call PHP Script via bash (instead of cronjob) recursively untill it is finished

How is this possible? At the Moment I am using cronjobs limited to one per min...

https://redd.it/11dkl5n
@r_bash
Q: Is there more then one bash implementations, and on what gcc/clang build targets can it not build?

Found the following article on a subreddit. In the article it claims.

> The chief advantage of Rust here is that it deftly sidesteps any conceivable problems with differing Bash implementations, and because Rust supports a wide range of build targets...

I'm not here to talk about rust vs bash.

But it feels the author is making untruthful claims about bash for example:

1. Is there different bash implementations(not shell)? or the user naively just mixing ash, bash, zsh, fish, etc?

2. Does rust support any build target you cannot build bash for?

Because last time i checked rustc it does not have great platform support except for tier 1, which is laughable compared to where bash can be executed.

If im naive or ignorent about the above topics please guide me in the right directions.

Thanks,

following article: https://determinate.systems/posts/determinate-nix-installer

https://redd.it/11dyr4f
@r_bash
Understanding coreutils fmt command

I don't completely understand why fmt works as it does. Let say we have this piece of text:

By default, blank lines, spaces between words, and indentation are preserved in the output;
successive input lines with different indentation are not joined; tabs are expanded on input and
introduced on output.

When I execute fmt -c <path/to/file_with_this_text> I expect third line indented as the second one but it doesn't happen. Why? While it happens documentation tells:

> Crown margin mode: preserve the indentation of the first two lines within a paragraph, and align the left margin of each subsequent line with that of the second line.

And what paragraph is here? Is it some block of text delimited by one empty lines or not?

https://redd.it/11e2s11
@r_bash
What is wrong with my lockfile?

So, my understanding of a lockfile is a simple file that's created to show that a noscript is running, and to abort any future executions of the noscript if the lockfile exists when they started.

The problem I'm facing is that I implemented a lockfile but when I left it to run, it appears to have ended all instances of my noscript. I came back to no noscripts running, the process incomplete, and the lockfile not being deleted.

Here's what I've written that concerns the lockfile.

At start of noscript:

if [ -f "$LOCKFILE" \]; then

echo "Instance already running. - Exiting"

exit 3

fi

downloaddate=$(date -Iseconds -u)

echo "Download in progress started $downloaddate." > "$LOCKFILE"

And at the end:

rm "$LOCKFILE"

https://redd.it/11e8b8a
@r_bash
Have section of jq a variable?

I have the following in a bash noscript:

jq -n --arg fullTitle "$2" \
--arg shortnoscript "$5" \
--arg speakerName "$7" \
--arg series "$saseries" \
--arg denoscription "$descr" \
--arg eventcategory "$eventcategory" \
--arg socialnoscript "$4" \
'{
"acceptCopyright": true,
"fullTitle": $fullTitle,
"displayTitle": $shortnoscript,
"speakerName": $speakerName,
"subnoscript": $series,
"moreInfoText": $denoscription,
"eventType": $eventcategory,
"socialSharing": [{
"platform": "twitter",
"message": "\"\( $socialnoscript )\"",
"useVideoClip": true
},
{
"platform": "facebook",
"message": "\"\( $socialnoscript )\"'\\n\\n'\( $denoscription )",
"useVideoClip": true
}],
"social_sharing_video_clip": {
"start": 0.0,
"end": 120.0
}
}' \
> $SADATA

I'm looking to have this section completely disappear under certain circumstances:

{
"platform": "twitter",
"message": "\"\( $socialnoscript )\"",
"useVideoClip": true
},

I was thinking that I should somehow make this a variable so that it can go from:

"socialSharing": [{
"platform": "twitter",
"message": "\"\( $socialnoscript )\"",
"useVideoClip": true
},
{
"platform": "facebook",
"message": "\"\( $socialnoscript )\"'\\n\\n'\( $denoscription )",
"useVideoClip": true
}],
"social_sharing_video_clip": {
"start": 0.0,
"end": 120.0
}

to:

"socialSharing": [{
"platform": "facebook",
"message": "\"\( $socialnoscript )\"'\\n\\n'\( $denoscription )",
"useVideoClip": true
}],
"social_sharing_video_clip": {
"start": 0.0,
"end": 120.0
}

How can I do this, or is there a better way than making a section of jq a variable?

https://redd.it/11eiplh
@r_bash
Need progress bar in wget or use curl for large file

I'm in a pickle. Originally, I was using curl in my noscript to upload (see bottom for uploading command):

#!/bin/bash

SRVPATH=/srv/dev-disk-by-uuid-49e4aa1a-279a-45ce-b23e-467c2b2a4162
MEDIA_DIR=$SRVPATH/Archive/2023
MEDIA_FILENAME=2023-02-28_11-04-23.mp4
MEDIA_PATH="${MEDIA_DIR}/${MEDIA_FILENAME}"

ENDPOINT="https://api.website.com/v2/media"

JSON="{
\"ID\": \"22823239276459\",
\"uploadType\": \"original-video\",
\"originalFilename\": \"${MEDIA_FILENAME}\"
}
"

UPLOAD_RESPONSE=$(
curl -s \
-H "X-API-Key: <myAPIKEY>" \
-H "Content-Type: application/json" \
-X POST \
-d "$JSON" \
$ENDPOINT
)

GET_URL_SNIPPET="
import json
import sys
print(json.loads(sys.stdin.read())['uploadURL'])
"

URL=$(echo $UPLOAD_RESPONSE | python -c "$GET_URL_SNIPPET" )

echo $URL

curl --progress-bar \
-H "X-API-Key: ${API_KEY}" \
-X POST \
--data-binary "@$MEDIA_PATH" \
$URL \
|& cat

Everything worked great when uploading a small mp4 and I could see the progress bar moving along. When I go to upload a large mp4, say, 2.3 GB on my 2 GB RAM system, I get `curl: option --data-binary: out of memory`. Using `-T` resulted in `405: Method Not Allowed` and using Using `-F` resulted in `File must be uploaded as HTTP body`.

Enter wget:

wget --header "X-API-Key: ${API_KEY}" --post-file $MEDIA_PATH $URL

#instead of

curl --progress-bar \
-H "X-API-Key: ${API_KEY}" \
-X POST \
--data-binary "@$MEDIA_PATH" \
$URL \
|& cat

Works to upload a large file. But I have tried:

wget --header "X-API-Key: ${API_KEY}" --show-progress --upload-file $MEDIA_PATH $URL
wget --header "X-API-Key: ${API_KEY}" --progress=bar --upload-file $MEDIA_PATH $URL
wget --header "X-API-Key: ${API_KEY}" --progress=bar:force --post-file $MEDIA_PATH $URL
wget --header "X-API-Key: ${API_KEY}" --progress=dot --post-file $MEDIA_PATH $URL
wget --header "X-API-Key: ${API_KEY}" --progress=dot:mega --post-file $MEDIA_PATH $URL
wget -v --header "X-API-Key: ${API_KEY}" --post-file $MEDIA_PATH $URL

And none of these will show the progress bar while the file is uploading. I can see the progress bar AFTER the file is uploaded:

https://upload.website.com/path
--2023-02-28 19:23:03-- https://upload.website.com/path
Resolving upload.website.com (upload.website.com)... 12.345.678.912
Connecting to upload.website.com (upload.website.com)|12.345.678.912|:443... connected.

And then after it's finished uploading:

HTTP request sent, awaiting response... 201 Created
Length: 94 [text/plain]
Saving to: ‘path’

path 100%[=================================================================>] 94 --.-KB/s in 0s

2023-02-28 19:23:48 (3.34 MB/s) - ‘path’ saved [94/94]

Am I SOL and have to settle for no progress bar? I'm looking for either a way to use curl to upload a large file, or wget to show the progress bar.

https://redd.it/11eo8vp
@r_bash