r_bash – Telegram
Aligning Two Columns for Files and Directories in Bash from Bottom-Up

[What I am trying to do](https://imgur.com/a/UjzUqXe)

I am working on a bash navigation noscript that displays files and directories side by side in two columns. However, I am stuck on aligning the output properly.
> I am hoping when its finished I can post it here and get some feedback. The noscript has some nice abilities which I have wanted for CLI interaction.

### The Problem:
When you look at the screenshot, the outputs don't align properly at the bottom. I need the files on the left and directories on the right, and both should start from the bottom and grow upwards.

### Why it’s Important:
The main issue I want to solve is that when there are many files, you have to scroll up to see the directories, which defeats the ease of navigation. I want the directories and files to always stay visible, both aligned properly from the bottom, like in my picture.

The main display:

display_items_fileNav() {
# Get terminal height using tput
term_height=$(tput lines)

# Get the outputs of the existing functions
file_output=$(display_files_only) # Get the file output
dir_output=$(display_dir_only) # Get the directory output

# Determine how many lines are used for each output
file_lines=$(echo "$file_output" | wc -l)
dir_lines=$(echo "$dir_output" | wc -l)

# Calculate the maximum of the file and directory lines to ensure both align from the bottom
max_lines=$(( file_lines > dir_lines ? file_lines : dir_lines ))

# Set the start position for both columns so they align at the bottom
start_position=$((term_height - max_lines - 3)) # Reserve 3 lines for the prompt and buffer

# Set the column width for consistent spacing; adjust based on the longest file name
file_column_width=40 # Adjust this as needed
dir_column_width=30 # Adjust this as needed

# Pad the top so the output aligns to the bottom of the terminal
tput cup $start_position 0

# Combine the outputs, aligning the columns side by side
paste <(echo "$file_output" | tail -n "$max_lines") <(echo "$dir_output" | tail -n "$max_lines") | while IFS=$'\t' read -r file_line dir_line; do
printf "%-${file_column_width}s %s\n" "$file_line" "$dir_line"
done

# Print category noscripts (Files and Directories) at the top of each column
echo -e "${NEON_GREEN}Files:${NC}$(printf '%*s' $((file_column_width - 5)) '')${NEON_RED}Directories:${NC}"

# Move cursor to the prompt position and show the prompt
tput cup $((term_height - 1)) 0
}

**The output functions** (I did this because I could not get the reverse order to properly display).




display_dir_only() {
# Get terminal height using tput
term_height=$(tput lines)

# Get directories and files
dirs=($(ls -d */ 2>/dev/null)) # List directories
files=($(ls -p | grep -v /)) # List files (excluding directories)

# Reverse the order of directories and files
dirs=($(printf "%s\n" "${dirs[@]}" | tac)) # Reverse the directories array
files=($(printf "%s\n" "${files[@]}" | tac)) # Reverse the files array

dir_count=${#dirs[@]} # Count directories
file_count=${#files[@]} # Count files
total_count=$((dir_count + file_count)) # Total number of items (directories + files)

# Calculate how many lines we need to "pad" at the top
padding=$((term_height - total_count - 22)) # 6 includes prompt space and a clean buffer

# Pad with empty lines to push content closer to the bottom
for ((p = 0; p < padding; p++)); do
echo ""
done

# Skip file display but count them for numbering
reverse_index=$total_count # Start reverse_index from the total count (dirs + files)

# First, we skip file output but count files
reverse_index=$((reverse_index - file_count))

# Then, display directories in reverse order
with correct numbering
for ((i = 0; i < dir_count; i++)); do
if [ $reverse_index -eq $current_selection ]; then
printf "${NEON_RED}%2d. %s${NC}/ <---" "$reverse_index" "${dirs[i]}"
else
printf "${NEON_RED}%2d. %s${NC}/" "$reverse_index" "${dirs[i]}"
fi
reverse_index=$((reverse_index - 1))
echo ""
done echo ""}




display_files_only() {
# Get terminal height using tput
term_height=$(tput lines)

# Get directories and files
dirs=($(ls -d */ 2>/dev/null)) # List directories
files=($(ls -p | grep -v /)) # List files (excluding directories)

# Reverse the order of directories and files
dirs=($(printf "%s\n" "${dirs[@]}" | tac)) # Reverse the directories array
files=($(printf "%s\n" "${files[@]}" | tac)) # Reverse the files array

dir_count=${#dirs[@]} # Count directories
file_count=${#files[@]} # Count files
total_count=$((dir_count + file_count)) # Total number of items (directories + files)

# Calculate how many lines we need to "pad" at the top
padding=$((term_height - total_count - 24)) # 6 includes prompt space and a clean buffer

# Pad with empty lines to push content closer to the bottom
for ((p = 0; p < padding; p++)); do
echo ""
done

# Skip directory display but count them for numbering
reverse_index=$total_count # Start reverse_index from the total count (dirs + files)

# First, skip directory display but count directories
# The reverse_index skips by the dir_count, so it correctly places files after.
reverse_index=$((reverse_index))

# Then, display files with correct numbering (including counted but hidden directories)
for ((i = 0; i < file_count; i++)); do
if [ $reverse_index -eq $current_selection ]; then
printf "${NEON_GREEN}%2d. %-*s${NC} <---" "$reverse_index" $COLWIDTH "${files[i]}"
else
printf "${NEON_GREEN}%2d. %-*s${NC}" "$reverse_index" $COLWIDTH "${files[i]}"
fi
reverse_index=$((reverse_index - 1)) # Decrease the reverse_index each time
echo ""
done

# Add an empty line for clean separation between the listing and the prompt
echo ""
}


### Any ideas or suggestions on how to fix this alignment issue?

https://redd.it/1fq69nt
@r_bash
Unsure as to how I would pull this off

My Synology runs my OpenVPN server. I have the "keepalive 10 60" directive and 2 concurrent sessions / user account is allowed for, which means if the user accidentally reboots without disconnecting from the VPN first, they'll be reconnected upon the next logon.

My issue is that I want to solve this by leaving in the keepalive directive as is, but running some bash noscript as a cron job for when users reboot without disconnecting the VPN first.

Synology support would only say I have the following tools available for this:

netstat

procfs (/proc/net/nfconntrack or /proc/net/ipconntrack)

ip (iproute2)

tcpdump : yes

I'm very new to bash and Unix. I've been googling but I'm unsure as to how I could implement this. I'd appreciate some help, thanks

https://redd.it/1fq9p8n
@r_bash
Automation Shell Script for CTFs

Here is the code: https://codefile.io/f/l9LmkIdHZK

I am new to shell noscripting; I just know few Linux Commands. I was hoping if someone could check the code I have written and help me improve my shell noscript skills. I am trying to build an automation noscript for CTF's. I want to save my time by not executing all same commands again and again for every target.

I know there's a lot of if statement. I want to know how to make this more effective and faster.

https://redd.it/1ft3dsf
@r_bash
TBD - A simple debugger for Bash

I played with the DEBUG trap and made a prototype of a debugger a long time ago; recently, I finally got the time to make it actually usable / useful (I hope). So here it is~ https://github.com/kjkuan/tbd

I know there's set -x, which is sufficient 99% of the time, and there's also the bash debugger (bashdb), which even has a VSCode extension for it, but if you just need something quick and simple in the terminal, this might be a good alternative.

It could also serve as a learning tool to see how Bash execute the commands in your noscript.

https://redd.it/1ft5r7h
@r_bash
Output a section of stdout

Imagine the output from wpctl status:

...
- Some info
- Some info

Audio:
- Some info
- ...
- Some info

Video:
- Some info
...

I want to get the block of output under "Audio", so the output between "Audio" and "Video". Is there a efficient way to achieve this, e.g. with sed or awk... or grep... ?

https://redd.it/1ftkvra
@r_bash
¿Cómo puedo realizar un noscript en Ubuntu que envíe correos electrónicos con el uso del disco desde la terminal?



Es una tarea nose si me pueden ayudar, ya investigue y no me sale nada alguien que me ayude porfa 🫠

https://redd.it/1ftz0pg
@r_bash
How can I make a noscript in Ubuntu that sends emails with disk usage from the terminal?

It's a task I don't know if you can help me, I've already investigated and nothing comes up, someone help me please 🫠

https://redd.it/1fuis7w
@r_bash
Help creating noscript to email on boot

I am looking for help in creating a noscript to email me when a system boots or reboots. I have tried various online sources but nothing seems to work. I would like to have my Raspberry Pi running Raspbian email me when it boots. I have frequent power outages and want to be able to have the always on Pi let me know when it boots so that I know the power had gone out and I can check the logs for the duration.

Can anyone help me with this?

https://redd.it/1fupucl
@r_bash
weird behavior from a bash line

hi there,

I wonder why :


find /home/jess/* -type f -iname "*" | wofi --show=dmenu | xargs -0 -I vim "{}"


returns


xargs: {}: No such file or directory

why the find arg isn't passed to vim ?
thx for help guys and girls

https://redd.it/1fuq7r2
@r_bash
what does the $ BY ITSELF mean in bash?

i understand it has something to do with variables but i googled it and it couldn't get a straight answer on what the $ alone means, so i wanted to ask here

thank you

https://redd.it/1fv4k1r
@r_bash
ffmpeg bash question - How to create bash to cut out intro and outro from multiple videos

I'm trying to cut the intro and outro out of multiple videos with different beginning times and different end times using ffmpeg

The code I know of that will do this from a single video is

"ffmpeg -ss 00:01:00 -to 00:02:00 -i input.mkv -c copy output.mkv"

But I don’t know how to tell ffmpeg to do this for multiple videos and to do this with different beginning times and different ending times so that it will do one right after the other

I am new to all of this so if anyone could help me, that would be amazing, thank you

https://redd.it/1fwjvy8
@r_bash
How do i change the colors of that bar?

https://preview.redd.it/w3hvszskswsd1.png?width=1032&format=png&auto=webp&s=5b31a400d02ea56e41adeb17da96327373068443

Hello, so i am using Chris Titus Tech's custom bash config but the colors dont fit with the pallete of my terminal (im making my system Dune themed).

Here is the .bashrc file: https://github.com/ChrisTitusTech/mybash/blob/main/.bashrc , i really tried to find where i can change those colors but couldnt find the line.
My ocd is killing me ;(

https://redd.it/1fwmwol
@r_bash
what does "echo $$" do?

so question, what does "echo $$" do?

some people are saying that it prints the PID of the current instance of the shell you are on

other people are saying that it prints the PID of "a" or "the" noscript that's currently executing?

which is it? or is it both?

thank you

https://redd.it/1fwp9lf
@r_bash
How do I replace part of a line with the output of a variable?

Hi all,

I am writing a noscript that will update my IPv4 on my Wireguard server as my dynamic IP changes. Here is what I have so far:

#! /bin/bash

CurrentIP= curl -S -s -o /dev/null http://ipinfo.io/ip

Wireguard
IP= grep -q "pivpnHOST=" /etc/pivpn/wireguard/setupVars.conf |tr -d 'pivpnHOST='

if "$Current_IP" = "$Wireguard_IP" ;then
exit
else
#replace WireguardIP with CurrentIP in setupVars.conf
fi
exit 0


when trying to find my answer I searched through stack overflow and think I need to use awk -v, however; I don't know how to in this case. Any pointers would be appreciated.

https://redd.it/1fwxq9l
@r_bash
Getting the “logname” of a PID

Say I log into a box with account “abc”. I su to account “def” and run a noscript, helloworld.sh, as account “def”. If I run a ps -ef | grep helloworld, I will see the noscript running with account “def” as the owner. Is there a way I can map that back to the OG account “abc” to store that value into a variable?

Context: I have a noscript where I allow accounts to impersonate others. The impersonation is logged in the noscript’s log via the logname command, but I also have a “current users” report where I can see who’s currently running the noscript. I’d like the current users report to show that, while John is running the noscript, it’s actually Joe who’s impersonating John via an su.

I’ve tried ps -U and ps -u, but obviously, that didn’t work.

https://redd.it/1fx6n52
@r_bash
Shell noscripting projects for 1 yoe helpdesk to get promoted to a new role?

What could that be?(in new company-switch)

https://redd.it/1fx6m6a
@r_bash
How do I finish a pipe early?

Hi.

I have this noscript that is supposed to get me the keyframes between two timestamps (in seconds). I want to use them in order to splice a video without having to reencode it at all. I also want to use ffmpeg for this.

My issue is that I have a big file and I want to finish the processing early under a certain condition. How do I do it from inside of an awk noscript? I've already used this exit in the early finish condition, but I think it only finishes the awk noscript early. I also don't know if it runs, because I don't know whether it's possible to print out some debug info when using awk. Edit: I've added print "blah"; at the beginning of the middle clause and I don't see it being printed, so I'm probably not matching anything or something? print inside of BEGIN does get printed. :/

I think it's also important to mention that this noscript was written with some chatgpt help, because I can't write awk things at all.

Thank you for your time.

https://pastebin.com/cGEK9EHH

#!/bin/bash
set -x #echo on
SOURCEVIDEO="$1"
START
TIME="$2"
ENDTIME="$3"

# Get total number of frames for progress tracking
TOTAL
FRAMES=$(ffprobe -v error -selectstreams v:0 -countpackets -showentries stream=nbreadpackets -of csv=p=0 "$SOURCEVIDEO")
if -z "$TOTAL_FRAMES" ; then
echo "Error: Unable to retrieve the total number of frames."
exit 1
fi

# Initialize variables for tracking progress
framesprocessed=0
start
frame=""
endframe=""
start
diff=999999
enddiff=999999

# Process frames
ffprobe -show
frames -selectstreams v:0 \
-print
format csv "$SOURCEVIDEO" 2>&1 |
grep -n frame,video,0 |
awk 'BEGIN { FS="," } { print $1 " " $5 }' |
sed 's/:frame//g' |
awk -v start="$START
TIME" -v end="$ENDTIME" '
BEGIN {
FS=" ";
print "start";
start
frame="";
endframe="";
start
diff=999999;
enddiff=999999;
between
frames="";
print "startend";
}
{
print "processing";
current = $2;

if (current > end) {
exit;
}

if (start
frame == "" && current >= start) {
startframe = $1;
start
diff = current - start;
} else if (current >= start && (current - start) < startdiff) {
start
frame = $1;
startdiff = current - start;
}

if (current <= end && (end - current) < end
diff) {
endframe = $1;
end
diff = end - current;
}

if (current >= start && current <= end) {
betweenframes = betweenframes $1 ",";
}
}
END {
print "\nProcessing completed."
print "Closest keyframe to start time: " startframe;
print "Closest keyframe to end time: " end
frame;
print "All keyframes between start and end:";
print substr(betweenframes, 1, length(betweenframes)-1);
}'

Edit: I have debugged it a little more and I had a typo but I think I have a problem with sed.

ffprobe -showframes -selectstreams v:0 \
-printformat csv "$SOURCEVIDEO" 2>&1 |
grep -n frame,video,0 |
awk 'BEGIN { FS="," } { print $1 " " $5 }' |
sed 's/:frame//g'

The above doesn't output anything, but before sed the output is:

38:frame 9009
39:frame 10010
40:frame 11011
41:frame 12012
42:frame 13013
43:frame 14014
44:frame 15015
45:frame 16016
46:frame 17017
47:frame 18018
48:frame 19019
49:frame 20020
50:frame 21021
51:frame 22022
52:frame 23023
53:frame 24024
54:frame 25025
55:frame 26026

I'm not sure if sed is supposed to printout anything or not though. Probably it is supposed to do so?

https://redd.it/1fxhx2n
@r_bash
How are if, case, etc implemented internally?

I was thinking about it and I realized I had no idea- how do if, for, while, case, etc, all control the execution of separate commands on other lines? For example


if [ "$thing" == "blah" ]; then
echo "How does it know to not run this command if thing is not blah??"
fi

Is this something only builtin commands have the power to do? Or could if, case, etc, theoretically be implemented as external programs?

https://redd.it/1fxnch3
@r_bash
this will probably be very complex

im tryting to create a noscript where i can pick up a text with some image links in the middle and input that into a tui like less will all the images loaded with ueberzug.

i know that is possible because there are noscripts like ytfzf that is capable of doing something close.

the tool im using to get the texts with image links in the middle is algia(terminal nostr client).

to be honest a vim tui would make it more usable but i dont know if this would be much more complex so something like less but that is capable o loading tui images would be more than enought.

i use alacritty.

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