r_bash – Telegram
Is there a way to save executed keyboard shortcuts from the cli to a file or to stdout?

Sometimes I'd be exploring the different keybinding I have and I accidentally pressed a combination (like Alt + U or I'd change from emacs to vim or whatever) but I wouldn't know what I'd press because I'm just messing around or I pressed this keyboard shortcut by accident.

Is there a way to output to stdout or save to a file that, for example, says I pressed alt + u and give a short denoscription that mentions I changed the text to upper case or I pressed ctrl + y and that yanks the line.

I accidentally fat finger my keyboard shortcuts all the time and I can't figure out what I just pressed. It would help me debug my keyboard shortcut and learn what I actually pressed.

https://redd.it/17sagaf
@r_bash
A few common shell functions (cat, mktemp, wc -c, and sleep) re-implemented in pure bash

I re-implemented a few common shell functions (that dont bash builtins with equivalent functionality) in pure bash. Anyone else do this? Anyone have any to add?

My use case for these tends to be to use them as "backups" when I want a code to be able to run on an embedded machine that has bash but everything else is not guaranteed. i.e.,

type -p FUNC >&/dev/null || {
FUNC() {
...
}
}

Here are the re-implemented functions. Each has a quick test along with it to ensure it is working. The functionality is not always an exact match to the original (not all flags are implemented...just the core functionality). But, for what is implemented it should (I think) be a drop-in replacement.

mktemp() {
local tmpFile

# generate tempfile name, and repeat until we get one that doesnt exist.
tmpFile=/tmp/.tmp.${RANDOM}
while [ -f "$tmpFile" ]; do
tmpFile=/tmp/.tmp.${RANDOM}
done

# touch tmpfile then echo its path
touch "${tmpFile}"
echo "${tmpFile}"
}

# test mktemp
file="$(mktemp)"
[ -f "${file}" ] && echo "tmpfile exists" >&2
echo


cat() {
if [ -t 0 ] && [ $# == 0 ]; then
# no input
return
elif [ $# == 0 ]; then
# only stdin
printf '%s\n' "$(</proc/self/fd/0)"
elif [ -t 0 ]; then
# only function inputs
source <(printf 'echo '; printf '"$(<"%s")" ' "$@"; printf '\n')
else
# both stdin and function inputs. fork printing stdin.
{ printf '%s\n' "$(</proc/self/fd/0)" >&9 & } 9>&1
source <(printf 'echo '; printf '"$(<"%s")" ' "$@"; printf '\n')
fi
}

# test cat
printf '%s\n' hi bye > "${file}"
printf '%s\n' hola adios | cat "${file}"
echo


wc() {
# only char/byte count (-c flag) implemented

# check for no input case
[ -t 0 ] && [ $# == 0 ] && return

# make tmpfile
local tmpFile fd waitFlag
tmpFile="$(mktemp)"

(
waitFlag=false

# add stdin, if anything is there
[ -t 0 ] || {
if [ $# == 0 ]; then
cat >&${fd}
else
# if we also are adding files then fork adding stdin
waitFlag=true
{ cat <&9 >&${fd} & } 9<&0
fi
}

# add function inputs that are files
for nn in "$@"; do
[ -f "$nn" ] && echo "$(<"${nn}")" >&${fd}
done

# wait for forked cat of stdin (if needed)
${waitFlag} && wait

# get the current position of fd
read </proc/self/fdinfo/${fd}
echo "${REPLY##$'\t'}"

) {fd}>>"${tmpFile}"

# remove tmpfile
[[ -f "${tmpFile}" ]] && \rm -f "${tmpFile}"

}

# test wc
printf '%s\n' hola adios | wc "${file}"
echo

sleep() {
local dur
# get sleep duration. default to 1 if missing.invalid
[[ "$1" =~ ^[0-9]
\.?0-9+$ ]] && dur="$1" || dur=1
(
# read from empty anonymous pipe with timeout
read -u ${fd} -t "$dur"
) {fd}<><(:)
}

# test sleep
echo "hi - ${EPOCHREALTIME}"
sleep 2
echo "bye - ${EPOCHREALTIME}"
echo

https://redd.it/17scg3v
@r_bash
Deferring process substitution

So here is a very basic example of process substitution:

bash --init-file <(echo "echo 4")

This will result in the number 4 being printed at the onset of a new bash session. However, in the following case, the number is not printed:

docker exec -it ubuntu_container bash --init-file <(echo "echo 4")

For anyone unfamiliar, this command connects to an existing docker container named 'ubuntu_container' and executes the bash command. Although this successfully results in starting a bash session within the container, the number 4 is not printed.

My best guess is that the process substitution executes immediately, resulting in a filepath that is valid outside the container, but invalid within the container. Thus it cannot be used when starting a bash session inside the container.

Does anyone know of a way to get this second example to work? My topic noscript refers to 'deferring' the process substitution because if I could defer it until after entering the docker container, I believe everything would work.

Thank you.

&#x200B;

(EDIT: For anyone curious, what I'm actually trying to do is to launch bash inside a docker container with a custom prompt by setting the PS1 environmental variable.)

https://redd.it/17smxs8
@r_bash
Help with basic folder perms (beginner)

Hey !
Im kinda new to bash, and im having a pretty basic problem here.
I have a minecraft server that restart, calling start.sh on restart.


When my ssh user do a bash start.sh, it works fine.
However, when the server execute it itself, the first instructions dont execute.
I'm pretty certain its a permission problem, but i cant figure why, because it should be accessible by everyone (first pic), and somehow, when the server restarts, the perms change (second pic)
Here is the bash i execute.



rm -r ./world
sleep 3

unzip -o lobby.zip -d world

sleep 3
java -Xmx3G -jar paper.jar #This get executed anyway


(sorry if there is code blocs, i dont know how)

&#x200B;

When user execute bash noscript

After restart

https://redd.it/17spxh4
@r_bash
PS1

I have recently started to use oh my bash and now I want to change the color of my PS1 (custome prompt) how should I do it.

I do not seem to have anything regarding PS1 in my .bashrc .

Please help

https://redd.it/17sqrm5
@r_bash
Glassfish/payara domain restart project, any improvements you would say?

function domain_action() {

    case $1 in

    1)

        echo "instruction received to start domain $2"

        /home/techyman/glassfish4/bin/asadmin start-domain "$2"

        ;;

    2)

        echo "instruction received to stop domain $2"

        /home/techyman/glassfish4/bin/asadmin stop-domain "$2"

        ;;

    3)

        echo "instruction received to restart domain $2"

        /home/techyman/glassfish4/bin/asadmin stop-domain "$2" && /home/techyman/glassfish4/bin/asadmin start-domain "$2"

        ;;

    esac



}

echo "What action do you want to perform? (1 for Start, 2 for Stop, 3 for Restart)"

read actionToPerform

echo "On which domains do you want to perform these actions?"

read -a arrayOfDomains

# https://stackoverflow.com/a/56146307/21719190

for domain in "${arrayOfDomains[@]}"; do

    domain_action "$actionToPerform" "$domain"

    #echo "$domain"

    #https://ryanstutorials.net/bash-noscripting-tutorial/bash-if-statements.php

    #if [ "$actionToPerform" = "1" ]; then

    #   echo "Starting $domain"

    #  domain_action "$actionToPerform" "$domain"

    #elif [ "$actionToPerform" = "2" ]; then

    #   echo "Stopping $domain"

    #  domain_action "$actionToPerform" "$domain"

    #else

    #   [ "$actionToPerform" = "3" ]

    #  echo "Restarting $domain"

    # domain_action "$actionToPerform" "$domain"

    #fi

done

https://redd.it/17tinew
@r_bash
man tool | cat | grep "string"

Out of curiosity, why doesn't grep work after cat? Isn't the stdout just a "textfile"? Ok, now thinking about this, I actually didn't try to run it with root privileges. But would it matter though?

https://redd.it/17tntom
@r_bash
How to remove single new lines from the end of a line in a text file, but ignore double new lines

I have been tearing my hair out trying to process some text files that have too many new lines.

I have a text file that look s something like this:

The quick brown fox jumps Over the
lazy dog. The quick brown fox.

The quick brown fox
jumps over the lazy dog.

I want to remove the single newlines but ignore the doubles.

In a text editor I can find and place using regex like this:

Find: \n(?!\n) Replace with: <space>

But I have a bunch of files, so I’m looking for a way I can create a noscript to do it.

I’ve tried see/gsed, but it is ignoring my regular expressions, even with the -E option. Even a simple search for a newline fails:

sed -i -E 's/\n/ /g' test.txt

Does anyone have a solution?

Many thanks.

https://redd.it/17twwyv
@r_bash
weird behaviors

curl -s https://english-e-reader.net/level/pre-intermediate | grep "/book/.*>" | sed 's/<a.*="//' | sed 's/">//' |sed 's|\^|https://english-e-reader.net|' | xargs -n 1 curl -s | grep -E "\^words: " >> out

I cannot write anything to the out file, but without redirecting to the file, everything went right.

https://redd.it/17v73mz
@r_bash
Is the -f in rm -rf a bit useless?

There's a lot of jokes about rm -rf but if the directory doesn't exist and you run rm -r, it would throw an error, no big deal.

But if it does exist and we run rm -r then it deletes the directory recursively. As a standalone command rm -rfdoesn't seem that much different from rm -r. So maybe I don't understand the joke about rm -rf but rm -r should be good enough? I mean we obviously can't delete something that doesn't exist and -f just suppresses that error message. The importance of -f seems to be overstated?

https://redd.it/17vgh0i
@r_bash
Monitor text file and run command on change?

I'm writing a now-playing Spotify noscript with semi cool formating...
When I ask playerctl for metadata I get a mpris:length (with a number) line, among the others.
I am currently giving that (number) to a Var and checking it every second and then re-running the noscript on change.
I read about a tool that can watch a file and run a command on change of file. I just can't remember what it was. I was thinking I could put the length into a txt file and watch it.


Is it worth using this other tool (that some great haxor will name) to watch the file?
I'm trying to lower system resource use of course.

https://redd.it/17vu88w
@r_bash
Trying to set a noscript that will move files to different directories based off size

I can’t figure out how to set a shell noscript that when I run it will allow me to move a files above or below a certain size into two different directories and was wondering if anyone knew how.

https://redd.it/17w47wx
@r_bash
Getting Currently playing from Spotify_Player

Trying to use inotifywait to watch the album art file to see when spotify\_player changes tracks then adding now playing data to a txt file for other use.


My issue is that I am getting the LAST song that was played.... what am I doing wrong?
If I cat I get last song played... if I run the playerctl in a terminal it is currently playing.
(sleeping before the echo did not work)

album_art="$HOME/.cache/spotify_player/image"
metadata_file="$HOME/.local/tmp/spotify.txt"

inotifywait -m -e access "$album_art" | while read changed_file; do
echo "$(playerctl -p spotify_player metadata noscript)" > $metadata_file
done

&#x200B;

https://redd.it/17w8iaz
@r_bash
Just in case this is useful to anyone else

I recently finished a function to validate the file extension of say, a list file or what have you, if you want to limit the filetype that can be passed to your noscript, and thought I'd share what I came up with:

#==========================================================================
# Check the validity of a file's file extension
# Invoked with: check_ext "<filepath>" <extension length> "<valid file format>"
# Globals: none
# Arguments: file path, length of file extension, accepted file extension
# Outputs: nothing
# Returns: 0 if extension is valid, 1 otherwise
#
# Notes: extension length should be the character length of the extension
# itself (e.g.: 2 for sh) plus the dot preceding the extension (e.g.:
# 3 for '.sh')
check_ext() {
local filePath="$1"
local extensionLength="$2"
local validFormat="$3"

fileName="${filePath##*/}"
fileExtension="${fileName: -${extensionLength}}"

if [[ "$fileExtension" == "$validFormat" ]]; then
return 0
else
return 1
fi

} # End of function 'check_ext'

I'm sure there's probably a better way to go about this, but this is the best I can come up with at this stage.

https://redd.it/17weust
@r_bash
Making a matrix

Hey, everyone! I'm still fairly new to bash and don't exactly know how to solve this exercise we received for studying. If anyone could help me, I would really appreciate that. Here's the text:
You are tasked to create a simple program that emulates a cinema ticket reservation system for a cinema with a single screen and 100 seats organised in a 10x10 grid.
The seating arrangement should be presented to the user as a 10x10 grid. Each seat is identified by its position in the grid (e.g. the first seat is at position 0,0 and the last seat is position 9,9). For visual representation, the program should use 'A' for available seats and '_' for reserved seats.
The program should begin by displaying a greeting message to the user and the current seating map, where all seats are initially available. It should then prompt the user to enter a seat number to reserve. After the user provides a valid seat number, the program should reserve that seat and display the updated seating map. If the seat is already reserved, the program should inform the user and prompt them to choose another seat.
After reserving a seat and showing the updated seating map, the program should ask the user whether they want to reserve another seat. If the user decides to continue, the program should repeat the reservation process. Otherwise, it should end with a closing message.

Thanks in advance to anyone who's willing to help me with this exercise.

https://redd.it/17wj6s0
@r_bash
Using an INT trap to dynamically debug a running noscript

I came up with a way to using `trap ... INT` to help dynamically debug a noscript/function as it is running. I find it quite useful, and figured others on /r/bash might as well.

Set the following trap at the start of the functions/noscripts you want this functionality enabled on:

trap 'printf '"'"'%s\n'"'"' "" "press [a] to Abort (exit)" "press [u] to Unset INT trap (makes <ctrl> + <c> work normally again)" "press [x] to eXecute a command" "press [p] to print the Present working directory" "press [i] to print Information about what caller/function/line/command is currently running" "press [d] / [D] to [start] (set -xv) / to [stop] (set +xv) printing Debug output to stderr" "press [v] / [V] to write Vars (declare -p) to [stderr] / to [file (${PWD}/.vars)]" "press [e] / [E] to write Environment (env) to [stderr] / to [file (${PWD}/.env)]" "press anything else to continue" >&2;
read -r -n 1;
case "$REPLY" in
a) exit ;;
u) trap - INT ;;
x) if [[ $USER == root ]] && [[ ${SUDO_USER} ]] && ! [[ ${SUDO_USER} == root ]] && type -a su &>/dev/null; then su -p "${SUDO_USER}" < <(read -r && echo "$REPLY"); elif ! [[ $USER == root ]]; then source <(read -r && echo "$REPLY"); else echo "for security running generic commands as root is not allowed" >&2; fi ;;
p) echo "$PWD" ;;
i) echo; [[ $FUNCNAME ]] && printf '"'"'function: %s\n'"'"' "$FUNCNAME" >&2; printf '"'"'caller : %s\n'"'"' "$0" >&2; [[ $BASH_LINENO ]] && printf '"'"'line : %s\n'"'"' "${BASH_LINENO}" >&2; printf '"'"'command : %s\n'"'"' "${BASH_COMMAND}" >&2 ;;
d) set -xv ;;
D) set +xv ;;
v) declare -p >&2 ;;
V) declare -p >"${PWD}"/.vars ;;
e) env >&2 ;;
E) env >"${PWD}"/.env ;;
esac' INT


This will make it so that when you press `<ctrl>` + `<c>` the following menu appears:

press [a] to Abort (exit)
press [u] to Unset INT trap (makes <ctrl> + <c> work normally again)
press [x] to eXecute a command
press [p] to print the Present working directory
press [i] to print Information about what caller/function/line/command is currently running
press [d] / [D] to [start] (set -xv) / to [stop] (set +xv) printing Debug output to stderr
press [v] / [V] to write Vars (declare -p) to [stderr] / to [file ($PWD}/.vars)]
press [e] / [E] to write Environment (env) to [stderr] / to [file ($PWD}/.env)]
press anything else to continue

The shell will then read 1 character and if it is one of the ones listed above it will run the corresponding action in the `case` statement from the `trap ... INT` definition. I chose these actions feeling that they might be of use when debugging a noscript, though of course you can modify/add/remove possible actions by redefining the trap.

***

One note regarding the "press [x] to eXecute a command" action:

As it is implemented above, it will not execute commands as root. If allowed to run commands as root, it would allow someone to hit `<ctrl>` + `<c>` on a noscript run with `sudo` and then execute generic commands (outside the scope of what the noscript was intended to do) as root. Which is dangerous.

If run as root and you press `x` at the INT trap menu it will try and run your command as the (non-root) `$SUDO_USER` (the user you ran `sudo` from) using `su`. Unfortunately, this runs the command in a subshell, meaning you cannot use it to modify any parameters of the running noscript, which limits its usefulness.

If anyone knows how to run a command in the current (root) shell as a non-root user let me know and ill incorporate it. If you are OK with the security risks of running generic commands as root from the trap menu you can replace the `case` statement's definition for `x` with

x) source <(read -r && echo "$REPLY") ;;

https://redd.it/17wqep9
@r_bash
any tips why its not working?



if [[ $current_url != "${NGROK_REMOTE_URL}"  \]\];
then
curl -s -X POST "https://api.telegram.org/botapi/sendMessage" -d "chat_id=secret" -d text=${NGROK_REMOTE_URL}
current_url=${NGROK_REMOTE_URL}
fi

https://redd.it/17wtqme
@r_bash
Does anyone have a clue how to do this

Script 4: The server that hosts the images that you process with your previous shell noscript has been having connectivity problems. You want to write a shell noscript named checkserver.sh that you can schedule to run at night to ping the server and capture the results in a file. ping is a command to send packets to another computer to verify you can connect to it. Your noscript should take the IP address of the server as a parameter. For testing purposes, you may use 173.255.195.185. Your noscript should ping the server 10 times, save the output in a file and quit. The output file should include the date and time the ping was executed.

https://redd.it/17wxyau
@r_bash