r_bash – Telegram
How to configure terminal to show the entire previous command, without truncating it with an ellipsis?

Using iterm2 on MacOS with ZSH and powerlevel10k and Oh-My-Zsh. Nothing unusual.

When I paste a long `curl` command (with a request body that has a few dozen lines or more) into the terminal and execute it, I want to see the entire command when I press the Up arrow key to reload the last command from my history.

But what actually happens is only the last 30 or so lines of the command are shown when I press the Up arrow key, truncating all the lines above with an ellipsis (...).

I want to configure my terminal to actually display the *whole* entire command when I press Up.

I assume this is a config issue somewhere either in my `\~/.zshrc` file or the `\~/.p10k.zsh` file, but have no clue if that's correct.

https://redd.it/1ic5jhd
@r_bash
jq throwing parse errors

I have the following in a file called test.txt:

```
[
[
"a",
"b"
],
[
"c",
"d"
]
]
```

I inserted it into a shell variable like this:

```
$ test_records=$(cat test.txt)
```

When I echo test_records, I get this:

```
$ echo $test_records
[ [ "a", "b" ], [ "c", "d" ] ]
```

When I iterate through, I get the following:

```
$ for record in $test_records; do echo $record; done
[
[
"a",
"b"
],
[
"c",
"d"
]
]
```

Note the opening and closing brackets which I think are related to the issue. Anyway, when I try to pipe the result of the echo to jq, I get the following:

```
$ for record in $test_records; do echo $record | jq '.[0]'; done
jq: parse error: Unfinished JSON term at EOF at line 2, column 0
jq: parse error: Unfinished JSON term at EOF at line 2, column 0
jq: error (at <stdin>:1): Cannot index string with number
jq: parse error: Expected value before ',' at line 1, column 4
jq: error (at <stdin>:1): Cannot index string with number
jq: parse error: Unmatched ']' at line 1, column 1
jq: parse error: Unfinished JSON term at EOF at line 2, column 0
jq: error (at <stdin>:1): Cannot index string with number
jq: parse error: Expected value before ',' at line 1, column 4
jq: error (at <stdin>:1): Cannot index string with number
jq: parse error: Unmatched ']' at line 1, column 1
jq: parse error: Unmatched ']' at line 1, column 1
```

As I said, I think this is because of the opening and closing brackets. If so, why are they there? If not, what's the issue with the filter string?

Thanks,
Rob

https://redd.it/1idrbfy
@r_bash
Can I get a variable, at all times, to keep the output of the last command?

To capture the output of a command, I do

2>&1|tee capture.log

, but this is tedious and I find myself always needing it.

Is it possible to do some magic in the background, so that the output of the last command is always captured in an environment variable?

I don't want to prefix the command with something like "capture" and I don't want to suffix it, with "2>&1";)


I just want the variable, at all times, to keep the output of the last command.

https://redd.it/1ie270l
@r_bash
New to grep - why are these commands returning different results?

I'm working through the Sander van Vugt RHCSA video course, and on one of the labs you're asked to "use grep to show the names of all the files in /etc that have lines that contain the text 'root' as a word."

The solution he suggest is to change your directory to /etc, and run grep 'root\\b' * 2> /dev/null which returns something like this:

https://preview.redd.it/8v6irsjkq8ge1.png?width=834&format=png&auto=webp&s=2fc253b31c6eafb2a9b53351a5150bd084763a4b

However, if I run grep 'root\\b' *2 /etc 2> /dev/null from my home directory, I get this:

https://preview.redd.it/ahneo97fr8ge1.png?width=522&format=png&auto=webp&s=a58b0001a3d8d6a3e094bd3f14ae28817c42d6bb

If I remove the 2> /dev/null to see my STDERR, I see these errors:

https://preview.redd.it/da5nd9dtq8ge1.png?width=358&format=png&auto=webp&s=3088ab8cc2515c994b7f035dba125899874dc87d

And I'm not clear on why that's the case. In the other examples he's provided, we use grep to search files in other directories. I'm sure I'm missing a flag somewhere.

I had looked into using --directories=recurse which does return results, but they different than what I see if I run grep 'root\\b' * 2> /dev/null directory from /etc:

https://preview.redd.it/pb4dz2m5s8ge1.png?width=848&format=png&auto=webp&s=1f9df5f5b743dfe188a11d43c65dc2ad236d7f60

I know I'm misunderstanding something, but I'm not sure what and I don't know if I understand grep well enough to ask the right question. In the end, what I'd like to know is if I can use grep to look into a different directory from my home directory, and what I need to be doing differently if that is an option.

https://redd.it/1ie4t0x
@r_bash
Is this the right way of processing an array with elements containing white spaces?

The following function takes a list of arguments and searches for elements in the form "--key=value" and prints them in the form "--key value", so for instance "aaa --option=bbb ccc" gets converted into "aaa --option bbb ccc".

expand_keyval_args() {
local result=()
for arg in "$@"; do
if [[ "$arg" == --*=* ]]; then
key="${arg%%=*}"
value="${arg#*=}"
printf "%s %q " "${key}" "${value}"
else
printf "%q " "${arg}"
fi
done
}


The way I deal with values containing white spaces (or really any character that should be escaped) is by using "%q" in printf, which means I can then do the following if I want to process an array:

local args=( ... )
local out="$(expand_keyval_args "${args[@]}")"
eval "args=(${out})"


Is it the best way of doing this or is there a better way (that doesn't involve the "eval")?

https://redd.it/1iekm3s
@r_bash
Check for any one of the background commands run by a loop exits with success

I have a loop that runs bluetooth command in the background (tries to connect to bluetooth devices with a timeout of X seconds).

If any one of those commands run by the loop exits (which can only mean either timeout of X seconds has passed after attempting to connect devices or a device has connected, which is usually immediately), then exit the noscript, else do something.

connect_trusted() {
local device
for device in $(bluetoothctl devices Trusted | cut -f 2 -d ' '); do
# this command runs in background, exiting immediately with success on
# connection or failure after timeout of 5 seconds has passed
bluetoothctl -t 5 connect "$device" &
done
}

# if even just 1 device was connected, exit noscript immediately since no more action is needed
if connect_trusted; then
exit 0
# else, launch bluetooth menu after 5 seconds have passed (implied when bluetooth command exits with failure)
else
do_something
fi

------------

How to check that "any one of the `bluetoothctl -t 5 connect "$device" &` commands" exited with success to then exit the noscript, else `do_something`?

https://redd.it/1ifdcpg
@r_bash
Anyone ever try to use Tmux + friends to build a TUI app?

Anyone ever try to use Tmux as the basis for a TUI for a bash app? Perhaps combined with `dialog`/`whiptail`, `fzf`, `bat`, `watch`, etc. It could even include some tmux plugins.

TUI apps similar to `lazygit`, `lazydocker` and wtfutil could possibly be quickly written as a bash noscript inside of a tmux layout.


Possible skeleton (untested):

#!/bin/bash

# app_name - denoscription of app_name
# usage:
# app_name <options>

set -euo pipefail

_dispatch() {
case "$1" in
"_start_tui")
shift
_start "$@"
;;
"_pane0_1")
shift
_loop _pane0_1
;;
"_pane0_2")
shift
_loop _pane0_2
;;
*)
_start_tmux "$@"
;;
esac
}

_loop() {
while sleep 5; do "$@" || true; done
}

_start_tmux() {
# enable tmux to run inside of tmux
unset TMUX TMUX_PANE TMUX_PLUGIN_MANAGER_PATH tmux_version
export TMUX_SOCKET="$(mktemp -u)"
# re-run self with $1=_layout
exec tmux \
-S "$TMUX_SOCKET" \
-p ~/.config/app_name \
-f ~/.config/app_name/tmux.conf \
-c "'$0' _start_tui $(printf '%q ' "$@")"
}

_start_tui() {
# TODO: unbind the prefix key, to disable the default keybinds.
# TODO: capture ctrl-c/INT to kill tmux (not individual pane noscripts)

_layout "$@" &
_loop _pane0_0
}

_layout() {
# TODO: layout panes. examples:
tmux split-window -h -t 0.0 "$0" _pane0_1
tmux split-window -v -t 0.1 "$0" _pane0_2
# TODO: settings
# TODO: app key bindings
# TODO: process command line options
}

# definitions of panes

_pane0_0() {
# noscript for window 0 pane 0

date
}

_pane0_1() {
# noscript for window 0 pane 1

top
}

_pane0_2() {
# TODO: noscript for window 0 pane 2
}

_dispatch "$@"



https://redd.it/1ies4ig
@r_bash
Can't seem to get the correct pid when using this bash noscript I'm working on. Any help?

When using this noscript: https://pastecode.io/s/py42w4xn (via usernoscripts on unraid)

The pid in the logs is not the same as the one that's showing when i run a ps aux | grep "[s]leep 10"

It always seems to be off one. What am I doing wrong here?

The goal is to basically reset a timer every time there's a update from inotifywait and then at the end perform a command.

Thanks!

https://redd.it/1ielvng
@r_bash
Total Newbie at Bash Scripting

I'm trying to create a noscript to download and datestamp YouTube videos. I can download the videos, but it comes down with the name given by it's creator. I want to append the upload date to the front of the filename. Any help is appreciated. My noscript so far:

read -p "Enter YouTube URL: " yt_url

echo "YouTube URL = ${yt_url}"



read -p "Enter upload date: " upload_date

echo "Upload Date = ${upload_date}"



file=$(yt-dlp --get-filename -o "%(noscript)s.mp4" $yt_url)

echo "File = ${file}"



yt-dlp -f mp4 "$yt_url"



https://redd.it/1iedal0
@r_bash
Custom bash noscript dependency graph

Hi all!
Some time ago I started to write a little bash noscript to check some kubernetes stuffs I need to check. By the time this noscript has become so huge with a lot of functions and variables. Sometimes I need to edit some things but I’m starting to get lost in the functions. Is there any automated way to create a graph that contains all the functions and them dependencies?

Thank you!

https://redd.it/1ig9d5f
@r_bash
How would you efficiently process every line in a file? while read is 70x slower than Python

I have written a lot of shell noscripts over the years and in most cases for parsing and analyzing text I just pipe things around to grep, sed, cut, tr, awk and friends. The processing speeds are really fast in those cases.

I ended up writing a pretty substantial shell noscript and now after seeding its data source with around 1,000 items I'm noticing things are slow enough that I'm thinking about rewriting it in Python but I figured I'd post this to see if anyone has any ideas on how to improve it. Using Bash 4+ features is fine.

I've isolated the slowness down to Bash looping over each line of output.

The amount of processing I'm doing on this text isn't a ton but it doesn't lend itself well to just piping data between a few tools. It requires custom programming.

That means my program ends up with code like this:

while read -r matched_line; do
# This is where all of my processing occurs.
echo "${line}"
done <<< "${matches}"

And in this case `${matches}` are lines returned by grep. You can also loop over the output of a program too such as `done < <(grep ...)`. On a few hundred lines of input this takes 2 full seconds to process on my machine. Even if you do nothing except echo the line, it takes that amount of time. My custom logic to do the processing isn't a lot (milliseconds).

I also tried reading it into an array with `readarray -t matched_lines` and then doing a `for matched_line in "${matched_lines[@]}"`. The speed is about the same as while read.

Alternatively if I take the same matches content and use Python using code like this:

with open(filename) as file:
for line in file:
print(line)

This finishes in 30ms. It's around 70x faster than Bash to process each line with only 1,000 lines.

Any thoughts? I don't mind Python but I already wrote the tool in Bash.



https://redd.it/1ifvg1m
@r_bash
Url-encode get string with multiple arguments?

I have one string that's like
action=query&format=json&list=allpages&aplimit=max&apfilterredir=nonredirects&apprefix=Wp/akz&apcontinue=Wp/akz/Bréhéville
If I put it into the url without encoding, it breaks because it contains special characters. If I put the whole thing into --data-urlencode it encodes the &s and treats it all as one argument.
Soo, what do I do?

https://redd.it/1iftomw
@r_bash
can you explain what this does?

echo '[q]sa[ln0=aln256%Pln256/snlbx]sb5567320342535949633984860024054390510049758475925810612727383477870370412074937779308150930912981042snlbxq'|dc



(It is in a single line)

https://redd.it/1ighyqf
@r_bash
I need your help

Hello, I am quite new on Linux and I wanted to make a bash noscript that has my Linux desktop environment, customisation, apps etc at once because I switch computers quite often and don't want the hassle of doing these every time I switch devices. If it's possible a yt video would be very helpful but I appreciate all the answers. Thank you!

https://redd.it/1ifj9me
@r_bash
nesting command substitutions

My goal is to use dmenu to browse a small set of applications. A list of such applications is in \~/prj/dmenus/favorites/a.txt. If I invoke $(cat ~/prj/dmenus/favorites/a.txt | dmenu)

I get just what I'm after. If I invoke

$(cat ~/prj/dmenus/favorites/a.txt | dmenu -fn 'Droid Sans Mono-18')

I get a output that is nicer to read. Next step, I would like to put the formatting options in a file. I can access that file and read it into a variable by another command substitution.

Example:x=$(<~/.config/dmenu/layout.txt); echo $x yields -fn 'Droid Sans Mono-18'

That is as far as I get. Can't seem to execute in the out command substitution.

$(cat ~/prj/dmenus/favorites/a.txt | dmenu $x)

usage: dmenu [-bfiv] [-l lines] [-p prompt] [-fn font] [-m monitor]

[-nb color] [-nf color] [-sb color] [-sf color] [-w windowid]

Not what I want Similarly, if I use

$(cat ~/prj/dmenus/favorites/a.txt | dmenu $(<~/.config/dmenu/layout.txt))

usage: dmenu [-bfiv] [-l lines] [-p prompt] [-fn font] [-m monitor]

[-nb color] [-nf color] [-sb color] [-sf color] [-w windowid]

Same failure. I bet the solution is really simple, and will enlighten me immensely.

I am using ubuntu 24.04 with fluxbox.

Thanks

Ti











https://redd.it/1ih44b2
@r_bash
Is there a way to get History without <enter>?

Hi, I'd like to get a past command of history for example !1900 but without enter, so I can rewrite that command for this instance and then manually I will do then <enter> for this new changed command?

Regards!

https://redd.it/1ih5bpo
@r_bash
Sed/awk help

Hi, I have text files that contain lists of numbers. Each number is on a separate line. Some of the numbers have forward slashes in the middle (eg 11152/3), some of them don't (eg 11276), which is fine.

However due to the way I collected the data, there are some lines that just have an assortment of slashes and spaces on them and nothing else.

Is there any way I can use sed or awk to get rid of the unwanted slashes whilst keeping the wanted ones?

https://redd.it/1ihd4yv
@r_bash
looking for a way to have a yes or no option at the end of a noscript to start another noscript or exit.

I have a simple backup noscript that creates archives of data. At the end of the noscript it encrypts and then uploads to a cloud server.

I'd like to make this into two noscripts with an option at the end of the first to run the second noscript or exit. i.e, I don't always want to encrypt and upload.

Any ideas?

https://redd.it/1ihisxo
@r_bash
Window Tiling Script w/ xdotool and wmctrl not persistent after switch workspaces

So I'm running xfce4 as my DE (w/ xfwm4 as the WM) and the window tiling that comes default is awesome \*if\* you're using a monitor(s) with normal dimensions. I got a nice ultrawide monitor a while back and the tiling, while still effective, doesn't quite tile the way it would on a standard monitor. I've been meaning to write a noscript to tile more effectively on an ultrawide monitor for a while now and I **finally got around to it** about a week ago.

Things are going great and it works exactly as expected (sort of). I pasted the code below (but I must warn you I'm still pretty new to bash noscripting so there might be an simpler way to accomplish the same thing). I basically find what window is active with xdotool, figure out what monitor that window is on (with some wizardry I found on StackExchange), and tile the window with wmctrl based on the argument passed to the noscript. Then I just programmed each of the variations with different arguments to different keyboard shortcuts and \*chef's kiss\*

**Here's the problem:** every time I change workspaces and change back, one or more of the windows I've tiled with my noscript move around to a different position and size. Is there any reason this could be happening with my noscript or could it be something else in the window manager overriding things?



`# This noscript is meant to tile windows into smaller regions`

`# than what is available by default in xfce4.`

`#`

`# Ultra-wide monitors are effective as a seamless dual monitor,`

`# but window tiling acts different. This is a fix for that issue.`

`# Don't bother using this noscript on a standard monitor. It will`

`# work, but the windows will be unusable.`

`#`

`# This noscript will separate the monitor into 8 regions, 4 on`

`# the top half of the screen and 4 on the bottom, with each`

`# given a letter signifier representing a physical mapping of`

`# a keyboard, like so:`

`#`

`# -----------------`

`# | Q | W | E | R |`

`# |---------------|`

`# | A | S | D | F |`

`# -----------------`

`#`

`# Additionally, there will be 4 more regions with 100% height,`

`# from left to right:`

`#`

`# -----------------`

`# | | | | |`

`# | H | J | K | L |`

`# | | | | |`

`# -----------------`

`#`

`# This gives a total of 12 tiling variations available that`

`# mimic default tiling on a standard monitor. Simply pass`

`# the letter designation of the region you wish to tile your`

`# focused window to as the only argument.`

`#`

`# For example:`

`# 'window-tile.sh -Q' tiles the active window to the top-left`

`# region.`

`#`

`# Each variation can be tied to keyboard shortcuts for easy tiling.`

`# I used <ctrl>+<super>+<letter>`







`# Get active window as decimal using xdotool`

`FOCUSED=$(xdotool getactivewindow)`



`# Convert decimal value to hex for use with wmctrl`

`FOCUSED=$( echo "obase=16; $FOCUSED" | bc )`

`FOCUSED=$( echo "0x0$FOCUSED" | awk '{print tolower($0)}' )`



`# Thanks to terdon from the PowerUser StackExchange for this`

`# next section to determine the current monitor.`



`## Get screen info`

`screen1=($(xrandr | grep -w connected | awk -F'[ +]' '{print $1,$3,$4}' |`

`head -n 1))`

`screen2=($(xrandr | grep -w connected | awk -F'[ +]' '{print $1,$3,$4}' |`

`tail -n 1))`



`## Figure out which screen is to the right of which`

`if [ ${screen1[2]} -eq 0 ]`

`then`

`right=(${screen2[@]});`

`left=(${screen1[@]});`

`else`

`right=(${screen1[@]});`

`left=(${screen2[@]});`



`fi`



`## Get window position`

`pos=$(xwininfo -id $(xdotool getactivewindow) | grep "Absolute upper-left X" |`

`awk '{print $NF}')`



`## Which screen is this window displayed in? If $pos`

`## is greater than the offset of the rightmost screen,`

`## then the window is on the right hand one`



`# Parse resolution of current monitor and assign to`

`# $WIDTH and $HEIGHT`

`if [ "$pos" -gt "${right[2]}" ]`

`then`

`# echo
"${right[0]} : ${right[1]}"`

`IFS=x read -r WIDTH HEIGHT <<< ${right[1]}`

`else`

`# echo "${left[0]} : ${left[1]}"`

`IFS=x read -r WIDTH HEIGHT <<< ${left[1]}`

`fi`



`# Tile the focused window based on argument passed.`

`# Position and size is determined by the resolution of the current moniter:`

`# if $HEIGHT=1440 and I want the window to equal half the height of the`

`# screen, I would use $(( $HEIGHT / 2 )). Enter 'man wmctrl' in your`

`# terminal prompt to get more information on the wmctrl command.`



`if [ $1 = '-Q' ]`

`then`

`wmctrl -ir $FOCUSED -e 0,0,0,$(( $WIDTH / 4 )),$(((( $HEIGHT / 2 )) - 1))`

`elif [ $1 = '-W' ]`

`then`

`wmctrl -ir $FOCUSED -e 0,$(( $WIDTH / 4 )),0,$(( $WIDTH / 4 )),$(((( $HEIGHT / 2 )) - 1))`

`elif [ $1 = '-E' ]`

`then`

`wmctrl -ir $FOCUSED -e 0,$(( 2 * (( $WIDTH / 4 )))),0,$(( $WIDTH / 4 )),$(((( $HEIGHT / 2 )) - 1))`

`elif [ $1 = '-R' ]`

`then`

`wmctrl -ir $FOCUSED -e 0,$(( 3 * (( $WIDTH / 4 )))),0,$(( $WIDTH / 4 )),$(((( $HEIGHT / 2 )) - 1 ))`

`elif [ $1 = '-A' ]`

`then`

`wmctrl -ir $FOCUSED -e 0,0,$(( $HEIGHT / 2)),$(( $WIDTH / 4 )),$(( $HEIGHT / 2 ))`

`elif [ $1 = '-S' ]`

`then`

`wmctrl -ir $FOCUSED -e 0,$(( $WIDTH / 4 )),$(( $HEIGHT / 2 )),$(( $WIDTH / 4 )),$(( $HEIGHT / 2 ))`

`elif [ $1 = '-D' ]`

`then`

`wmctrl -ir $FOCUSED -e 0,$(( 2 * (( $WIDTH / 4 )))),$(( $HEIGHT / 2 )),$(( $WIDTH / 4 )),$(( $HEIGHT / 2 ))`

`elif [ $1 = '-F' ]`

`then`

`wmctrl -ir $FOCUSED -e 0,$(( 3 * (( $WIDTH / 4 )))),$(( $HEIGHT / 2 )),$(( $WIDTH / 4 )),$(( $HEIGHT / 2 ))`

`elif [ $1 = '-H' ]`

`then`

`wmctrl -ir $FOCUSED -e 0,0,0,$(( $WIDTH / 4 )),$(( $HEIGHT ))`

`elif [ $1 = '-J' ]`

`then`

`wmctrl -ir $FOCUSED -e 0,$(( $WIDTH / 4 )),0,$(( $WIDTH / 4 )),$(( $HEIGHT ))`

`elif [ $1 = '-K' ]`

`then`

`wmctrl -ir $FOCUSED -e 0,$(( 2 * (( $WIDTH / 4 )))),0,$(( $WIDTH / 4 )),$(( $HEIGHT ))`

`elif [ $1 = '-L' ]`

`then`

`wmctrl -ir $FOCUSED -e 0,$(( 3 * (( $WIDTH / 4 )))),0,$(( $WIDTH / 4 )),$(( $HEIGHT ))`

`else`

`echo "Argument required"`

`fi`



https://redd.it/1iirxja
@r_bash