r_bash – Telegram
Newbie here - Need Help With Positioning Windows

Hello, i recently started to follow a bash coding course for beginners, i take notes and experiment with things i learn while following the course so i have 3 windows that are open all the time while i follow this course and for the sake of coding something that does something useful, i decided write a noscript that opens all those 3 windows and positions them as i prefer, so far noscript looks like this;

\#!/bin/bash

xed \~/Desktop/Studies/"note1.md" &

celluloid \~/Desktop/Studies/"plist1.m3u" &

xfce4-terminal &

sleep 5

wmctrl -r "note1.md (\~/Desktop/Studies)" -e 0,687,72,679,697 &

wmctrl -r "01 - Bash Scripting for Beginners: Complete Guide to Getting Started - Course Introduction (Part 1).mp4" -e 0,0,0,672,460 &

wmctrl -r "Terminal - vuaaaaaaa@vuaaaaaaa-E502SA: \~" -e 0,4,522,665,247 &

It works, but coordinates are a little bit messy and i don't know why, heres the "wmctrl -lG" for the correct layout of windows;

wmctrl -lG

0x03400003 0 7 522 665 247 vuaaaaaaa-E502SA Terminal - vuaaaaaaa@vuaaaaaaa-E502SA: \~

0x03800003 0 0 0 672 460 vuaaaaaaa-E502SA 01 - Bash Scripting for Beginners: Complete Guide to Getting Started - Course Introduction (Part 1).mp4

0x03600325 0 676 72 690 697 vuaaaaaaa-E502SA note1.md (\~/Desktop/Studies)



How it is supposed to look like

How it is looking

TLDR; Can't get coordinates of the windows that i am trying to open via a noscript right.

https://redd.it/1n9wdp2
@r_bash
AI sucks, but so do I. Help needed.

Hi there,

I've been trying to get a bash noscript running properly on my synology for the last 10 hours, aided by chatGPT. With each iteration the AI offered, things worked for some time until they did not.

I want the noscript to run every 6 hours, so it has to self-terminate after each successful run. Otherwise Synology task scheduler will spit errors. I know that crontab exists, but I have SSH disabled usually and the DSM GUI only offers control over the built-in task scheduler and I want to pause the backup function at certain times without re-enabling SSH in order to access crontab.

I am trying to make an incremental backup of files on an FTP server. The folder /virtual contains hundreds of subfolders that are filled with many very small files. Each file is only a few to a few hundred bytes large.

Therefore, I asked chatGPT to write a noscript that does as follows:

1. Create an initial full backup of the folder /virtual
2. On the next run, copy all folders and files locally from the previous backup to a new folder with a current timestamp.
3. Connect to the FTP server and download only newly created or changed folders and/or files inside those folders.
4. terminate the noscript

This worked to a certain degree, but I noticed that a local copy of the previous folders into a new one with the current timestamp confuses lftp, hence downloading every file again.

From here on out everything got worse with every solution ChatGPT offered. Ignore the timestamps of the local folders, copy the folders with the previous timestamp, only check for changed files inside the folders and new folders against the initial backup....

At the end, the noscript was so buggy, it started to download all files and folders from the root directory of the FTP server. I gave up at this point.

Here is the noscript in its last, semi-working state.
It still downloads all 15k small files on each run, copies only the folder structure.
This is what I want to fix. Please keep in mind that I can only use FTP. No SFTP, no rsync.

Thanks a lot for your input!

`#!/bin/bash`

`# ========== CONFIGURATION ==========`

`FTP_HOST="serverIP"`

`FTP_USER="ftp-user"`

`FTP_PASS="password"`

`# Local backup paths`

`BASE_BACKUP_DIR="/volume/BackupServer/local_backup"`

`STORAGE_BACKUP_DIR="$BASE_BACKUP_DIR/storage"`

`VIRTUAL_BACKUP_DIR="$BASE_BACKUP_DIR/virtual"`

`LOG_DIR="$BASE_BACKUP_DIR/logs"`

`# Max backup versions to keep`

`MAX_ROTATIONS=120`

`# Timestamp`

`NOW=$(date +"%Y-%m-%d_%H-%M")`

`# Log file`

`mkdir -p "$LOG_DIR"`

`LOGFILE="$LOG_DIR/backup_$NOW.log"`

`# Lockfile to prevent concurrent execution`

`LOCKFILE="$BASE_BACKUP_DIR/backup_noscript.lock"`

`# ========== PREVENT MULTIPLE INSTANCES ==========`

`if [ -e "$LOCKFILE" ]; then`

`echo "[$(date +"%Y-%m-%d %H:%M:%S")] ERROR: Script is already running." | tee -a "$LOGFILE"`

`exit 1`

`fi`

`touch "$LOCKFILE"`

`trap 'rm -f "$LOCKFILE"; exit' INT TERM EXIT`

`# ========== FUNCTIONS ==========`

`rotate_backups() {`

`local dir=$1`

`cd "$dir" || exit 1`

`local backups=( $(ls -1d 20* 2>/dev/null | sort) )`

`local count=${#backups[@]}`

`if (( count >= MAX_ROTATIONS )); then`

`local to_delete=$((count - MAX_ROTATIONS + 1))`

`for ((i=0; i<to_delete; i++)); do`

`echo "Deleting old backup: ${backups[$i]}" | tee -a "$LOGFILE"`

`rm -rf "${backups[$i]}"`

`done`

`fi`

`}`

`cleanup_old_logs() {`

`echo "[*] Cleaning up log files older than 15 days..." | tee -a "$LOGFILE"`

`find "$LOG_DIR" -type f -name "backup_*.log" -mtime +15 -exec rm -f {} \;`

`}`

`backup_storage() {`

`echo "[*] Backing up /storage/backup/011" | tee -a "$LOGFILE"`

`local dest_dir="$STORAGE_BACKUP_DIR/$NOW"`

`mkdir -p "$dest_dir"`

`timeout 7200 lftp -u "$FTP_USER","$FTP_PASS" "$FTP_HOST" <<EOF 2>&1 | tee -a "$LOGFILE"`

`set ftp:passive-mode true`

`set net:timeout 300`

`set net:max-retries 2`

`mirror --verbose /ftpServer/main/folder/to/storage/backup/011 "$dest_dir/011"`

`quit`

`EOF`

`rotate_backups "$STORAGE_BACKUP_DIR"`

`}`

`backup_virtual_incremental() {`

`echo "[*] Backing
up /storage/virtual (incremental)" | tee -a "$LOGFILE"`

`local dest_dir="$VIRTUAL_BACKUP_DIR/$NOW"`

`mkdir -p "$dest_dir"`

`# === STEP 1: Copy entire content from previous backup before download ===`

`local last_backup=$(ls -1d "$VIRTUAL_BACKUP_DIR"/20* 2>/dev/null | sort | tail -n 1)`

`if [ -d "$last_backup" ]; then`

`echo "[*] Copying previous backup from $last_backup to $dest_dir..." | tee -a "$LOGFILE"`

`# Copy folder structure first`

`rsync -a --include='*/' --exclude='*' "$last_backup/" "$dest_dir/" | tee -a "$LOGFILE"`

`# Then copy files that don't exist yet`

`rsync -a --ignore-existing "$last_backup/" "$dest_dir/" | tee -a "$LOGFILE"`

`echo "[*] Copy from previous backup complete." | tee -a "$LOGFILE"`

`else`

`echo "[!] No previous backup found. Starting fresh." | tee -a "$LOGFILE"`

`fi`

`# === STEP 2: FTP mirror with only-newer logic ===`

`echo "[*] Downloading updated and new files from FTP..." | tee -a "$LOGFILE"`

`local lftp_log="/tmp/lftp_virtual_$$.log"`

`> "$lftp_log"`

`timeout 7200 lftp -u "$FTP_USER","$FTP_PASS" "$FTP_HOST" <<EOF > "$lftp_log" 2>&1`

`set ftp:passive-mode true`

`set net:timeout 300`

`set net:max-retries 2`

`mirror --only-newer --parallel=4 /ftpServer/main/folder/to/storage/virtual "$dest_dir"`

`quit`

`EOF`

`local changed_files_count`

`changed_files_count=$(grep -E '^Transferring|^=>|^<=|^Removing' "$lftp_log" | wc -l)`

`echo "[*] FTP sync complete. Files changed or added: $changed_files_count" | tee -a "$LOGFILE"`

`cat "$lftp_log" >> "$LOGFILE"`

`rm -f "$lftp_log"`

`rotate_backups "$VIRTUAL_BACKUP_DIR"`

`}`

`# ========== MAIN ==========`

`echo "===== Backup started at $NOW =====" | tee -a "$LOGFILE"`

`mkdir -p "$STORAGE_BACKUP_DIR"`

`mkdir -p "$VIRTUAL_BACKUP_DIR"`

`backup_storage`

`backup_virtual_incremental`

`cleanup_old_logs`

`echo "===== Backup finished at $(date +"%Y-%m-%d %H:%M:%S") =====" | tee -a "$LOGFILE"`

`# Cleanup`

`rm -f "$LOCKFILE"`

`trap - INT TERM EXIT`

https://redd.it/1na0c4p
@r_bash
declare -c var

Is declare -c var a reliable way of lower-casing all letters in a phrase except the first? That's what it appears to do (contrary to ChatGPT's assertion that it lower-cases all the letters). However, I can't find any documentation of the -c option.

https://redd.it/1nb6n57
@r_bash
Manipulate folder path in shell noscript variable

Greetings...

I've got kind of a dumb problem. I've got environment variables that define a path. Say for example
/var/log/somefolder/somefolder2

What I'm trying to do is set the folder to a path to the folder up two folders from that
/var/log

These aren't the folders... just trying to give a tangible example... the actual paths are dynamic.

I've set the variables to just append `../` which results in a variable that looks like this /var/log/somefolder/somefolder2/../../ and it seems like passing this variable into SOME functions / utilities works, but others it might not?

I am wondering if anyone has any great way to actually take the first folder and some how get the folder up some arbitrary number of folder levels up. I know dirname can give me the base, or parent of the current path, so should I just run dirname setting the newpath to the dirname of the original x number of times or is there an easier way?

https://redd.it/1nbp7ve
@r_bash
bash-completion behaving weirdly for some commands

Firstly, I most probably damaged something in some way, I do not remember these commands behaving like this before.

When I type commands like cargo or pacman, instead of printing the results to stdout and leaving the input line as-it-is, the results get inserted into the input line. Examples:
pacman ^I^I results in
pacman  --database files help query remove sync upgrade version -D F Q R S U V h 

pressing TAB more time prints seemingly all packages i have installed.
git ^I^I behaves as its supposed to.
cargo ^I^I inserts all subcommands to the input line, cargo add ^I^I results in:
cargo add -h --help -v --verbose -q --quiet --color -p --package --features --default-features --no-default-features --manifest-path --optional --no-optional --rename --dry-run --path --git --branch --tag --rev --registry --dev --build --target --ignore-rust-version

I have things like starship, but commenting out and starting new terminal and shell also does not resolve it. bash --norc and bash --norc --noprofile do not have the completion, and bash --noprofile has the concerned issue.

https://redd.it/1nchch3
@r_bash
bash-completion behaving weirdly

I most probably messed up. When i write commands like `cargo` or `pacman` (there are more), every subcommand or option gets written to the line. Glimpse:

https://preview.redd.it/6mifxk6mi4of1.png?width=686&format=png&auto=webp&s=ae27f8a70a89b8e755522a7f54f6eb56488bda8a

https://preview.redd.it/b13rsj6mi4of1.png?width=931&format=png&auto=webp&s=eac79af427043449bd247933704da6ba662064bc

What and why is this happening?

$ pacman -Qi bash-completion
Name : bash-completion
Version : 2.16.0-1
Denoscription : Programmable completion for the bash shell
Architecture : any
URL : https://github.com/scop/bash-completion
Licenses : GPL-2.0-only
Groups : None
Provides : None
Depends On : bash
Optional Deps : None
Required By : None
Optional For : bash bash-language-server packagekit
Conflicts With : None
Replaces : None
Installed Size : 1008.82 KiB
Packager : Tobias Powalowski <tpowa@archlinux.org>
Build Date : Thu Jan 16 13:21:28 2025
Install Date : Wed Sep 3 15:53:27 2025
Install Reason : Explicitly installed
Install Script : No
Validated By : Signature

I tried commenting out this from my bashrc:

# Use bash-completion, if available
# [[ $PS1 && -f /usr/share/bash-completion/bash_completion ]] &&
# . /usr/share/bash-completion/bash_completion

# # Completion for dotfiles
# [[ $PS1 && -f /usr/share/bash-completion/completions/git ]] &&
# . /usr/share/bash-completion/completions/git &&
# __git_complete dotfiles __git_main

But the issue is still there.

https://redd.it/1ncg8yy
@r_bash
Quotes around whole string or just the variable?

I've both but I'm unsure as to what is more correct because I can't seem to find any documentations on this.

fullpath="$HOME/"dir
full
path="$HOME/dir"

If we were to follow the style of the first line, it would fail in situations where there is a space between the variable and the string that is being concatenated, like in the following example.

message="$greeting Bob"
message="$greeting" Bob

The last line would fail because "Bob" would be treated as a command.

https://redd.it/1nd70h7
@r_bash
What is the best task project manager

I love the terminal. I have made it so I can do everything that isn't media rich in the terminal. I however keep struggling with one thing.

Project/task manager. I love the concept of task warrior and its super solid, but where I struggle is it doesn't really offer a good hierarchy. Yes I know about the subject.sub.sub but it doesn't lay it out in a clean way. Any suggestions?

https://redd.it/1nhxwzl
@r_bash
Questions about github workflow

Warning... Github newbie here... I finally got a github account going; I was ready to give up at one point. My current problem...
- I want to pull down a skeleton repo
- Throw in some text files, including an executable noscript
- Update and push the files to the repo and save changes

- The repo is https://github.com/NoAcadia3546/bash-conway-life/releases/tag/v0.1.0-alpha (it's public)
- On my desktop PC (linux) I'm in directory ~/life
- On desktop I execute

git pull https://github.com/NoAcadia3546/bash-conway-life/releases/tag/v0.1.0-alpha

...and I get the error message...

fatal: not a git repository (or any of the parent directories): .git

Did I not "finish" the repo, somehow? A separate question about "form"... should README.md contain the full documentation, or should it include a pointer to another file called "readme.txt"?

https://redd.it/1ni3faq
@r_bash
any reference about gtrash cmd?

Hi, I don't understand the use of trash-restore cmd, I don't understand where I should BE at the moment of restoring a file: in the destiny path of a file to be restored or in any other place. I don't understand how to get the numbered list of file....

May be this another cmd helps me: https://github.com/umlx5h/gtrash?tab=readme-ov-file

Thank you and Regards

https://redd.it/1niefrk
@r_bash
How can I convert all videos in a directory from webm to kmv using ffmpeg

this is the command to convert a webm to mk format is something like this

ffmpeg -i input.webm -c:v copy -c:a copy -c:s srt output.mkv

How do I do that to all the videos in a directory. Also, I would want the output to be the original file name, and the only change being the extension

https://redd.it/1nio4ow
@r_bash
Project Rating

Hi,

I found a problem few months ago, I believe it was on this sub.

The problem was that he needs to convert .md files into standalone .md files, by including images inside the md file as base64 instead of the url, and I solve it after 1 week of the post, but I did not find the post again,

Can you tell me your opinion on the project

https://github.com/ammr01/mdpics

https://redd.it/1niptkd
@r_bash
noob NUL-delimited question

Since filenames in Linux can contain newline-characters, NUL-delimited is the proper way to process each item. Does that mean applications/noscripts that take file paths as arguments should have an option to read arguments as null-delimited instead of the typical blank-space-delimited in shells? And if they don't have such options, then e.g. if I want to store an array of filenames to use for processing at various parts of a noscript, this is optimal way to do it:

mapfile -d '' files < <(find . -type f -print0)
printf '%s\0' "${files@}" | xargs -0 my-noscript

with will run `my-noscript` on all the files as arguments properly handling e.g. newline-characters?

Also, how to print the filenames as newline-separated (but if a *file* has newline in them, print a literal newline character) for readability on the terminal?

Would it be a reasonable feature request for applications to support reading arguments as null-delimited or is piping to `xargs -0` supposed to be the common and acceptable solution? I feel like I should be seeing `xargs -0` much more in noscripts that accept paths as arguments but I don't (not that I'd ever use problematic characters in filenames but it seems noscripts should try to handle valid filenames nonetheless).

[https://redd.it/1nip6kq

@r_bash
Documentation for Bash?

Hi there! I was looking for Bash documentation, so my question is: is there any official documentation about this? If not, what’s the best docu site you recommend?

https://redd.it/1niobmh
@r_bash
How to do this process to all the videos in a directory?

I want to embed a thumbnail into mkv file. The command is something like this:

ffmpeg -i input.mkv -attach image.jpg -metadata:s:t:0 mimetype=image/jpeg -c copy output.mkv

How can I do this to all the video files in the folder? The name each video, and thumbnail is the same, except the extension(.mkv and .jpg)

https://redd.it/1njhwim
@r_bash
How to solve this issue

so i am writing a noscript where i have like n files and everyfile just contain an array of same length so i want that the noscript iterate in the folder which contain that files ( a seprate folder) and read every file in loop 1 and in nested loop 2 i am reading and iterating the array i want to update some variables like var a i want that arr[0\] always do a=a+arr[0\] so that the a will be total sum of all the arr[0\].

For better understanding i want that the file contain server usage ( 0 45 55 569 677 1200) assume 10 server with diff value but same pattern i want the variable to be sum of all usage than i want to find do that it can be use in autoscaling.

current noscript so far

\#!/bin/bash

set -x

data="/home/ubuntu/exp/data"

cd "${data}"

count=1

avg=(0 0 0 0 0 0)

cpu_usr=0

cpu_sys=0

idle=0

ramused=0

ramavi=0

ramtot=0





file=(*.txt)



for i in "${file[@\]}"; do



echo "${i}"

mapfile -t numbers < "$i"

for j in "${numbers[@\]}"; do



val="${numbers[$j\]}"

clean=$(echo " $j " | tr -d '[:space:\]')

case $j in

*usr*) cpu_usr="clean" ;;

*sys*) cpu_sys="clean" ;;

*idle*) idle="clean" ;;

*ramus*) ramused="clean" ;;

*ramavi*) ramavi="clean" ;;

*ramtot*) ramtot="clean" ;;

esac



echo "$cpu_usr $cpu_sys $idle $ramused $ramavi $ramtot"

done

echo "$cpu_usr $cpu_sys $idle $ramused $ramavi $ramtot"

(( count++ ))

done

so i am stuck at iteration of array in a file

https://redd.it/1nji0zy
@r_bash
Conway's Life Game... implemented in bash

My Gmail account shares a 15 gigabyte pool that can also be accessed via drive.google.com. I gave up fighting Github, and uploaded "life.tgz" to Google Drive. Instructions for download...
- point your web browser at https://drive.google.com/file/d/1QvJXQpM8PAXAhU6FjSkAHPacMhHWgM7n/view?usp=drivelink
- click on the "Download" icon, 3rd from the right at the top, to dowmload
- copy or move downloaded life.tgz to where ever you please (except /dev/shm)
- extract with the command "tar xzf life.tgz"
- this should create a directory named "life"
- "cd life" and read the "readme.txt" file
- if you have "
$HOME/bin" in your path, it is strongly recommended to run "./setup". This noscript will create a "$HOME/bin/ttylife" symlink, enabling you to launch the game as "ttylife seedfile", without requiring the path to ttylife.
- ttylife will run in GUI terminals (e.g. xterm) and in true text consoles
- after launching ttylife, do NOT resize GUI term windows, or resize fonts in GUI windows or text consoles. If you want a maximized term window, do it before launching the game.
- if you have an older/slower machine, it may take a second or two to update after you tap the "n" key


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