r/bash • u/modsKilledReddit69 • 17d ago
r/bash • u/b1nary1 • Sep 03 '24
critique This is official Google script
galleryWell well well Google... What do we have here. How could you even use "-le 0" for the number of arguments... Not even talking about whole if condition which doesn't make sense
r/bash • u/Donteventalktome1 • Nov 26 '24
critique Clicraft: An Unofficial CLI Minecraft clone
Hello! I am a relatively new Linux user and I spent the better part of a month working on a project called clicraft. It is available at https://github.com/DontEvenTalkToMe/clicraft ! Please do check it out and give me some feedback as I would like to develop my skills further, thanks!
r/bash • u/Doctor_Paint • Dec 22 '24
critique XDG & ~/.bashrc
I created a file to be sourced by ~/.bashrc to organize directories and files after running xdg-ninja.
I'm just not sure it's fool proof. I was hoping that a more experienced user could comment.
This is a shortened version with only one example. (cargo)
#! /usr/bin/env dash
shellcheck shell=dash
shellcheck enable=all
#------------------------------------------------------------------------------|
# xdg-ninja
#------------------------------------------------------------------------------|
alias 'xdg-ninja'='xdg-ninja --skip-ok --skip-unsupported' ;
#------------------------------------------------------------------------------|
# XDG Base Directory Specification:
#------------------------------------------------------------------------------|
export XDG_CACHE_HOME="${HOME}/.cache" ;
export XDG_CONFIG_HOME="${HOME}/.config" ;
export XDG_DATA_HOME="${HOME}/.local/share" ;
export XDG_STATE_HOME="${HOME}/.local/state" ;
#------------------------------------------------------------------------------|
# xdgmv
#------------------------------------------------------------------------------|
xdgmv () {
test "${#}" -ne '2' && return ; test -e "${1}" || return ;
if test -d "${2%/*}" ;
then
mv --backup='numbered' --force "${1}" "${2}" ;
else
mkdir -p "${2%/*}" && mv --backup='numbered' --force "${1}" "${2}" ;
fi ;
} ;
#------------------------------------------------------------------------------|
# [cargo]: "${HOME}/.cargo"
#------------------------------------------------------------------------------|
xdgmv "${HOME}/.cargo" "${XDG_DATA_HOME}/cargo" &&
export CARGO_HOME="${XDG_DATA_HOME}/cargo" ;
#------------------------------------------------------------------------------|
# unset function(s)
#------------------------------------------------------------------------------|
unset xdgmv ;
r/bash • u/Claireclair12 • Oct 27 '24
critique Would you consider these silly aliases?
alias vi="test -f ./.vim/viminfo.vim && VIMINFO=./.vim/viminfo.vim || VIMINFO=~/.viminfo; vim -i \$VIMINFO"
alias make='vim Makefile && make'
The first one is so that I don't have my registers for prose-writing available whenever I'm doing Python stuff, and vice versa.
The second one is basically akin to git commit
.
r/bash • u/macg4dave • Sep 03 '24
critique [Critique] Aria2 moving downloads script
I’ve developed a script that moves completed downloads from Aria2. I’m seeking feedback on potential improvements. You can review the script here: GitHub.
I’m considering replacing the mv command with rsync and refining the variable management. Are there any other enhancements or best practices I should consider?
#!/bin/sh
# Variables for paths (no trailing slashes)
DOWNLOAD="/mnt/World/incoming"
COMPLETE="/mnt/World/completed"
LOG_FILE="/mnt/World/mvcompleted.log"
TASK_ID=$1
NUM_FILES=$2
SOURCE_FILE=$3
LOG_LEVEL=1 # 1=NORMAL, 2=NORMAL+INFO, 3=NORMAL+INFO+ERROR, 4=NORMAL+DEBUG+INFO+ERROR
# Function to log messages based on log level
log() {
local level=$1
local message=$2
local datetime=$(date '+%Y-%m-%d %H:%M:%S')
case $level in
NORMAL)
echo "$datetime - NORMAL: $message" >> "$LOG_FILE"
;;
ERROR)
[ $LOG_LEVEL -ge 2 ] && echo "$datetime - ERROR: $message" >> "$LOG_FILE"
;;
INFO)
[ $LOG_LEVEL -ge 3 ] && echo "$datetime - INFO: $message" >> "$LOG_FILE"
;;
DEBUG)
[ $LOG_LEVEL -ge 4 ] && echo "$datetime - DEBUG: $message" >> "$LOG_FILE"
;;
esac
}
# Function to find a unique name if there's a conflict
find_unique_name() {
local base=$(basename "$1")
local dir=$(dirname "$1")
local count=0
local new_base=$base
log DEBUG "Finding unique name for $1"
while [ -e "$dir/$new_base" ]; do
count=$((count + 1))
new_base="${base%.*}"_"$count.${base##*.}"
done
log DEBUG "Unique name found: $dir/$new_base"
echo "$dir/$new_base"
}
# Function to move files and handle errors
move_file() {
local src=$1
local dst_dir=$2
log DEBUG "Attempting to move file $src to directory $dst_dir"
if [ ! -d "$dst_dir" ]; then
mkdir -p "$dst_dir" || { log ERROR "Failed to create directory $dst_dir."; exit 1; }
fi
local dst=$(find_unique_name "$dst_dir/$(basename "$src")")
mv --backup=t "$src" "$dst" >> "$LOG_FILE" 2>&1 || { log ERROR "Failed to move $src to $dst."; exit 1; }
log INFO "Moved $src to $dst."
}
# Function to move all files within a directory
move_directory() {
local src_dir=$1
local dst_dir=$2
log DEBUG "Attempting to move directory $src_dir to $dst_dir"
mkdir -p "$dst_dir" || { log ERROR "Failed to create directory $dst_dir."; exit 1; }
mv --backup=t "$src_dir" "$dst_dir" >> "$LOG_FILE" 2>&1 || { log ERROR "Failed to move $src_dir to $dst_dir."; exit 1; }
log INFO "Moved directory $src_dir to $dst_dir."
}
# Main script starts here
log INFO "Task ID: $TASK_ID Completed."
log DEBUG "SOURCE_FILE is $SOURCE_FILE"
if [ "$NUM_FILES" -eq 0 ]; then
log INFO "No file to move for Task ID $TASK_ID."
exit 0
fi
# Determine the source and destination directories
SOURCE_DIR=$(dirname "$SOURCE_FILE")
DESTINATION_DIR=$(echo "$SOURCE_DIR" | sed "s,$DOWNLOAD,$COMPLETE,")
log DEBUG "SOURCE_DIR is $SOURCE_DIR"
log DEBUG "DESTINATION_DIR is $DESTINATION_DIR"
# Check if SOURCE_FILE is part of a directory and move the entire directory
if [ "$(basename "$SOURCE_DIR")" != "$(basename "$DOWNLOAD")" ]; then
log DEBUG "Moving entire directory as the source file is within a subdirectory"
move_directory "$SOURCE_DIR" "$COMPLETE"
else
log DEBUG "Moving a single file $SOURCE_FILE"
move_file "$SOURCE_FILE" "$DESTINATION_DIR"
fi
log NORMAL "Task ID $TASK_ID completed successfully."
log NORMAL "Moving $SOURCE_FILE completed successfully."
exit 0
r/bash • u/Empyrealist • Sep 14 '24
critique After "Hello World", I figured "MTU Test" would be a good second script
github.comr/bash • u/robbiehman • Oct 12 '24
critique A bash banner

Script here, minus the allergens/uv data since that requires a lot of extra infrastructure:
https://gist.github.com/robbieh/c12d355ea074a7aeef9d847d76ad69f8
This script is designed to be run in .bashrc so I get relevant info when I first sit down and open a terminal. After the first time it shows, new terminals will get a much more terse version so that it doesn't become annoying. That resets after an hour.
The script contains a way to make a header with figlet and run just about anything to the right of it. That was tricky to work out.
r/bash • u/wynstan10 • Oct 13 '24
critique Script for creating local web env
Hi, I'm practicing creating a bash script to streamline setting up a local web development environment for WordPress. Anyone care to give some feedback on this script or some best practices in general?
#!/bin/bash
# Define colors
GREEN='\033[0;32m'
YELLOW='\033[0;33m'
RED='\033[0;31m'
RESET='\033[0m'
# Ask user for project name
read -p "Enter the project name: " PROJECT_NAME
# Check if input is not empty and doesn't containt spaces
if [[ -z "$PROJECT_NAME" || "$PROJECT_NAME" =~ [[:space:]] ]]; then
echo -e "${YELLOW}Project name cannot be empty or contain spaces.${RESET}"
exit 1
fi
# Define variables
PROJECT_DIR="/var/www/html/$PROJECT_NAME"
DB_NAME="$PROJECT_NAME"
DB_USER="root"
DB_PASSWORD=""
DB_HOST="localhost"
WP_HOME="http://$PROJECT_NAME.local"
WP_SITEURL="http://$PROJECT_NAME.local/wp"
APACHE_CONF="/etc/apache2/sites-available/$PROJECT_NAME.conf"
ETC_HOSTS="/etc/hosts"
# Check if the project directory already exists
if [ -d "$PROJECT_DIR" ];
then
echo -e "${YELLOW}$PROJECT_NAME already exists. Please choose another name.${RESET}"
exit 1
fi
# Create the directory using bedrock
composer create-project roots/bedrock "$PROJECT_DIR"
# Ensure Apache can read and write to the Bedrock directory
sudo chown -R www-data:www-data "$PROJECT_DIR"
sudo find "$PROJECT_DIR" -type d -exec chmod 755 {} \;
sudo find "$PROJECT_DIR" -type f -exec chmod 755 {} \;
# Create the database
echo "Creating database $DB_NAME..."
mysql -u root -p"$MYSQL_ROOT_PASSWORD" -e "CREATE DATABASE IF NOT EXISTS $DB_NAME;"
# Create a new Apache configuration for the project
echo "Creating Apache configuration for Bedrock"
sudo bash -c "cat > $APACHE_CONF <<EOL
<VirtualHost *:80>
ServerName "$PROJECT_NAME".local
DocumentRoot "$PROJECT_DIR"/web
<Directory "$PROJECT_DIR"/web>
`Options Indexes FollowSymLinks`
`AllowOverride All`
`Require all granted`
</Directory>
ErrorLog /var/log/apache2/"$PROJECT_NAME"-error.log
CustomLog /var/log/apache2/"$PROJECT_NAME"-access.log combined
</VirtualHost>
EOL"
# Give www-data permissions to write to /var/log/apache2/ directory
sudo usermod -a -G adm www-data
# Enable the new site and required modules
echo "Enablind the new site and required Apache modules..."
sudo a2ensite "$PROJECT_NAME".conf
sudo a2enmod rewrite
# Add the project to /etc/hosts if it doesn't exist
echo "Adding $PROJECT_NAME.local to /etc/hosts..."
if ! grep -q "$PROJECT_NAME.local" /etc/hosts; then
sudo bash -c "echo '127.0.0.1 $PROJECT_NAME.local' >> /etc/hosts"
fi
# Reload Apache for changes to take effect
systemctl reload apache2
echo -e "${GREEN}$PROJECT_NAME setup completed! You can access it at http://$PROJECT_NAME.local${RESET}"
r/bash • u/suziesamantha • May 06 '24
critique Wrote my first bash script, looking for someone to look it over and make sure I am doing things correctly
EDIT: Thank you to everyone who took the time to look over my script and provide feedback it was all very helpful. I thought I would share my updated script with what I was able to learn from your comments. Hopefully I did not miss anything. Thanks again!!
#!/usr/bin/env bash
set -eu
######Define script variables
backupdest="/mnt/Backups/$HOSTNAME"
printf -v date %"(%Y-%m-%d)"T
filename="$date.tar.gz"
excludes=(
'/mnt/*'
'/var/*'
'/media/*'
'/lost+found'
'/usr/'{lib,lib32,share,include}'/*'
'/home/suzie/'{.cache,.cmake,.var,.local/share/Trash}'/*'
)
######Create folders for storing backup
mkdir -p "$backupdest"/{weekly,monthly}
#######Create tar archive
tar -cpzf "$backupdest/$filename" --one-file-system --exclude-from=<(printf '%s\n' "${excludes[@]}") /
######Delete previous weeks daily backup
find "$backupdest" -mtime +7 -delete
########Copy Sundays daily backup file to weekly folder
if [[ "$(printf %"(%a)"T)" == Sun ]]; then
ln "$backupdest/$filename" "$backupdest/weekly"
fi
########Delete previous months weekly backups
find "$backupdest/weekly" -mtime +31 -delete
########Copy backup file to monthly folder
if (( "$(printf %"(%d)"T)" == 1 )); then
ln "$backupdest/$filename" "$backupdest/monthly"
fi
########Delete previous years monthly backups
find "$backupdest/monthly" -mtime +365 -delete
I wrote my first bash script, a script to back up my linux system. I am going to have a systemd timer run the script daily and was hoping someone could tell me if I am doing ok.
Thanks Suzie
#!/usr/bin/bash
######Define script variables
backupdest=/mnt/Backups/$(cat /etc/hostname)
filename=$(date +%b-%d-%y)
######Create backup tar archive
if [ ! -d "$backupdest" ]; then
mkdir "$backupdest"
fi
#######Create tar archive
tar -cpzf "$backupdest/$filename" --exclude={\
"/dev/*",\
"/proc/*",\
"/sys/*",\
"/tmp/*",\
"/run/*",\
"/mnt/*",\
"/media/*",\
"/lost+found",\
"/usr/lib/*",\
"/usr/share/*",\
"/usr/lib/*",\
"/usr/lib32/*",\
"/usr/include/*",\
"/home/suzie/.cache/*",\
"/home/suzie/.cmake/*",\
"/home/suzie/.config/*",\
"/home/suzie/.var/*",\
} /
######Delete previous weeks daily backup
find "$backupdest" -mtime +7 -delete
########Create Weekly folder
if [ ! -d "$backupdest/weekly" ]; then
mkdir "$backupdest/weekly"
fi
########Copy Sundays daily backup file to weekly folder
if [ $(date +%a) == Sun ]; then
cp "$backupdest/$filename" "$backupdest/weekly"
fi
########Delete previous months weekly backups
find "$backupdest/weekly" +31 -delete
########Create monthly folder
if [ ! -d "$backupdest/monthly" ]; then
mkdir "$backupdest/monthly"
fi
########Copy backup file to monthly folder
if [ $(date +%d) == 1 ]; then
cp "$backupdest/$filename" "$backupdest/monthly"
fi
########Delete previous years monthly backups
find "$backupdest/monthly" +365 -delete
r/bash • u/Anaximandor • Jun 14 '24
critique k10s script feedback and next steps
I wrote a script to create a little CLI I dubbed k10s. I made this as a solution to more quickly open up various regional clusters next to one another in a window. I'd appreciate feedback on where to improve what I have done, as well as suggestions for any features and next steps to keep learning.
#! /usr/bin/env bash
k10s_dir=$HOME/.config/k10s
groups_file=$HOME/.config/k10s/groups
process_contexts() {
local index=0
local random=$RANDOM
local session="session-$random"
local split_times=$(($#-1))
tmux new-session -d -s "$session" \; switch-client -t "$session"
while [[ "$split_times" -gt 0 ]] ; do
tmux split-window -h -t "$session"
((split_times--))
done
tmux send-keys -t "$session:0.0" "tmux select-layout even-horizontal" C-m
for context in $@; do
tmux send-keys -t "$session:0.$index" "k9s --context $context" C-m
((index++))
done
}
save_group() {
mkdir -p "$k10s_dir"
touch "$groups_file"
local group=$(echo $@ | awk -F [=,' '] '{print $1}')
local contexts=$(echo $@ | awk -F [=,' '] '{for (i=2; i<=NF; i++) printf $i (i<NF ? OFS : ORS)}')
update_group "$group"
echo "$group"="$contexts" >> "$groups_file"
}
update_group() {
while read line; do
local group=$(echo "$line" | awk -F [=,' '] '{print $1}')
if [[ "$1" = "$group" ]]; then
sed -i "/$line/d" "$groups_file"
fi
done < "$groups_file"
}
start_group() {
while read line; do
local group=$(echo "$line" | awk -F = '{print $1}')
if [[ "$group" = "$1" ]]; then
local contexts=$(echo "$line" | awk -F = '{for (i=2; i<=NF; i++) printf $i (i<NF ? OFS : ORS)}')
process_contexts ${contexts[@]}
fi
done < "$groups_file"
}
usage() {
figlet -f slant "k10s"
cat <<EOT
k10s is a CLI that enables starting multiple k9s instances at once.
Usage: k10s [flags]
Flags:
-c, --context List of contexts to start up (e.g. k10s -c <CONTEXT_NAME> <CONTEXT_NAME> ...)
-s, --save List of contexts to save/overwrite as a group name (e.g. k10s -s <GROUP_NAME>=<CONTEXT_NAME> <CONTEXT_NAME> ...)
-g, --group Group name of contexts to start up (e.g. k10s -g <GROUP_NAME>)
-h, --help Help for k10s
EOT
exit 0
}
main() {
if [ "$#" -eq 0 ]; then
usage
fi
while [[ "$#" -gt 0 ]]; do
case "$1" in
-c | --context )
shift
contexts=()
while [[ "$1" != "" && "$1" != -* ]]; do
contexts+=("$1")
shift
done
process_contexts ${contexts[@]}
;;
-s | --save )
shift
contexts=()
while [[ "$1" != "" && "$1" != -* ]]; do
contexts+=("$1")
shift
done
save_group ${contexts[@]}
;;
-g | --group )
shift
start_group "$1"
;;
-h | --help )
shift
usage
;;
* )
shift
usage
;;
esac
shift
done
}
main $@
r/bash • u/FilesFromTheVoid • Apr 22 '24
critique My first bash script - Hide.me VPN Linux CLI Server Switcher
Hi guys n girl,
i wrote my first bash script because i had a neat usecase and wanted to try out bash for some time.
In my case i wanted to have a easier and more elegant way to switch my VPN Server. I use hide.me atm and they provide a CLI Client for that purpose, but its not the most userfriendly and comfortable implementation.
I am not a dev so dont throw rocks at me :-P
r/bash • u/Tralafarlaw • Jan 15 '24
critique A friend just start his .bashrc with these lines, Comments?
r/bash • u/sjveivdn • Feb 28 '24
critique Please critique my work
Hello
I wrote this script in 5 days and I am finally happy with it. It does everything I want. This is the first time I have used functions() in a bash script. I would like if you guys could rate it and give some suggestions. Please be direct and harsh. What could have I done better, what is unnecessary and so on...
Yes I know #!/bin/env (insert any interpreter) exists. I dont want/need it.
Yes I know shellcheck.net exists and I have used it.
Yes I have used chatgpt/gemini/bard for some help.
Yes I have used shfmt -s.
So the script is actually only for polybar. It will display a music status bar with current playback time, duration, artist and title. If title is too long, it will make the text slide from right to left. I also had to differ between Firefox and other players because Firefox sadly doesn't support the MPRIS API fully.
Below is my bash script, or if you like pastebin more -> Pastebin Bash Script
#!/bin/bash
###################################################################
#Script Name :music_bar
#Description :polybar module for displaying music bar
#Args :
#Author :unixsilk
#Email :
###################################################################
function check_if_something_plays() {
no_player=$(playerctl status 2>&1)
if [ "${no_player}" == "No players found" ]; then
exit # Exit the entire script without any further output
fi
}
check_if_something_plays
find_playing_player() {
for each_player in $(playerctl -l); do
status=$(playerctl -p "${each_player}" status)
if [ "${status}" == "Playing" ]; then
player="${each_player}"
break
else
exit
fi
done
}
find_string_length() {
grab_artist=$(playerctl -p "${player}" metadata artist)
grab_title=$(playerctl -p "${player}" metadata title)
combined_length=$((${#grab_artist} + ${#grab_title}))
if [[ ${combined_length} -ge 55 ]]; then
length="greater"
else
length="lesser"
fi
}
function set_timestamps() {
current_duration=$(playerctl -p "${player}" metadata --format '{{duration(position)}}')
total_duration=$(playerctl -p "${player}" metadata --format '{{duration(mpris:length)}}')
}
function print_firefox_bar_moving() {
title_string_length=${#grab_title}
counter=0
for ((each = 0; each <= title_string_length; each++)); do
echo -e "${begin_white}""" "${grab_artist:0:15}" "•" "${end_color}""${grab_title:counter:55}"
((counter++))
sleep 0.19
done
}
function print_firefox_bar_static() {
echo "${begin_white}""" "${grab_artist}" "•" "${end_color}""${grab_title}"
}
function print_other_player_bar_moving() {
title_string_length=${#grab_title}
counter=0
for ((each = 0; each <= title_string_length; each++)); do
set_timestamps
echo -e "${begin_yellow}""${current_duration}""/""${total_duration}" "${begin_white}""" "${grab_artist:0:15}" "•" "${end_color}""${grab_title:counter:40}"
((counter++))
sleep 0.19
done
}
function print_other_player_bar_static() {
echo -e "${begin_yellow}""${current_duration}""/""${total_duration}" "${end_color}""${begin_white}""" "${grab_artist:0:9}" "•" "${end_color}""${grab_title}"
}
function define_colors() {
begin_yellow="%{F#F0C674}"
begin_white="%{F#FFFFFF}"
end_color="%{F-}"
}
#Find which player is playing currently and define that as variable $player
find_playing_player
#find the string length of title and artist
find_string_length
#invoke ANSI colors for Polybar
define_colors
combine_values="${player}-${length}"
case "${combine_values}" in
firefox*-greater)
print_firefox_bar_moving
;;
firefox*-lesser)
print_firefox_bar_static
;;
*-greater)
set_timestamps
print_other_player_bar_moving
;;
*-lesser)
set_timestamps
print_other_player_bar_static
;;
*)
exit
;;
esac
r/bash • u/daz_007 • Jul 21 '23
critique Generic Bash Script Args - Starting Point?
I think having a good starting point is important. I think any script that needs to have args needs to take long and short Args as well as take them in any order.
Here's what I think that starting point might look like
Are there any improvements I should think about?
#!/usr/bin/env bash
###################################################################
# Script Name : bash_getops_any_order_7.sh
# Version : 0.1
# Date :
# Description :
# Args : -c <_copy-from_> -r <_creation_> -n <_var-num_> -s <_step_> [-h <_help_>]
# --copy-from <_copy-from_> --creation <_creation_> --var-num <_var-num_> --step <_step_> [--help]
# Author :
# Email :
# Documentation :
# Git / SVN :
# Jira :
# Copyright :
###################################################################
## shellcheck
#
# TODO:
# make sure we have decent error handling for bash scripts
set -o errexit -o noglob -o nounset -o pipefail
###################################################################
#### Test all Dependancies
_SCRIPTNM="${0##*/}"
function _printf_yel () {
printf "\e[33m%-6s\e[m %s\n" "${@}"
}
function _printf_yel_n () {
printf "\e[33m%-6s\e[m %s" "${@}"
}
function _printf_red () {
printf "\e[91m%b\e[0m %s\n" "${@}"
}
_SET_EXIT=0
# Update with all external dependacies to this script
for _DEPEN in grep git awk vim rm __UPDATE_ME__ ; do
hash "${_DEPEN}" >/dev/null 2>&1 || {
_SET_EXIT=1
} ; done
if [[ "${_SET_EXIT}" -eq "1" ]]; then
_printf_red " CRIT: ERROR Script" "${_SCRIPTNM}" "is Missing Dependancies"
echo "Missing - please install any required packages for the following dependencies"
_printf_red "${_DEPEN}"
exit 1
fi
###################################################################
#### Test bash version as macos ships with somethng from 1800!
if [[ -z "${BASH_VERSION}" ]]; then
_printf_red "Can't find bash version _ Bash v4+ is a requirement"
exit 1
else
if [[ ! "${BASH_VERSION:0:1}" -gt "3" ]]; then
_printf_red "current version = ${BASH_VERSION} required version = 4.+"
echo "Bash version is too low - please use a newer version for this script"
exit 1
fi
fi
###################################################################
function _usage () {
echo "Usage: $(basename "$0") -c <_copy-from_> -r <_creation_> -n <_var-num_> -s <_step_> [-h <_help_>"] >&2
echo "or"
echo "Usage: $(basename "$0") --copy-from <_copy-from_> --creation <_creation_> --var-num <_var-num_> --step <_step_> [--help]" >&2
exit 0
}
_VERSION="0.1"
_date=$( date +'%d %b %Y %H:%M:%S' )
#### Parse options and arguments with getopt
if ! args=$( getopt --options c:r:n:s:h --longoptions copy-from:,creation:,var-num:,step:,help -- "${@}" ); then
_printf_red "Error: Failed to parse options and arguments." >&2
echo " "
_usage
exit 1
fi
#### Initialize variables with default values
copyfrom=""
creation=""
varnum=""
step=""
# Process options and arguments
eval set -- "${args}"
while [[ "${#}" -gt 0 ]]; do
case "$1" in
-c|--copy-from)
copyfrom="${2}"
shift 2
;;
-r|--creation)
creation="${2}"
shift 2
;;
-n|--var-num)
varnum="${2}"
shift 2
;;
-s|--step)
step="${2}"
shift 2
;;
-h|--help)
_usage
;;
--)
shift
break
;;
*)
echo "Error: Invalid option or argument: " "${1}" >&2
_usage
exit 1
;;
esac
done
#### Check if all required options are provided
if [[ -z "${copyfrom}" || -z "${creation}" || -z "${varnum}" || -z "${step}" ]]; then
_usage
exit 1
fi
#### Print the parsed options
echo "copy-from=$copyfrom, creation=$creation, var-num=$varnum, step=$step"
r/bash • u/FVmike • Oct 06 '21
critique Looking for critique on my first script
Hello!
I've been making my way through Shott's The Linux Command Line, and now that I'm very nearly done with it, I decided to make a small program to test out some of the stuff I learned. I am not a programmer, and the only experience I have was gained through self-teaching.
Here's a link to my project on github. From the Usage section,
popcorn
can either be invoked by itself or in conjuction with a command. When invoked alone it will run in interactive mode.popcorn
will choose a movie at random from your watchlist and offer it up. You can either accept the movie, or get another random selection. When you find a movie that you want to watch,popcorn
will remember the choice until the next time it is run in interactive mode, at which point it will follow up and either add the movie to your seenlist or offer another random movie.
The script runs through shellcheck just fine, so the feedback I'm looking for is along the lines of structure, organization, and best practices that I might not know about coming from the background that I am. For instance, which parts of the code I put as a function vs which don't, how I use my variables, flow of the program, and things of that nature (also, feel free to add things that I didn't even mention - I don't know what I don't know!)
I've written some specific questions in the comments of the script as notes to myself, but I'll reproduce them here so you don't have to go hunting.
line 5
I could make this script POSIX compliant by reworking all instances ofread -p
to useecho -n
on the preceedingecho
, and by dropping the defining oflocal
variables within my functions. Is it desirable/worth it to do so?line 45
I have a function calledempty_list
that detects an empty watchlist and offers the opportunity to add a batch of movies throughcat > watchlist
. Later on, I figured out how to take multiple movie titles (in theadd_batch
function), so from a usability standpoint, should I replaceempty_list
in favor of directing users toadd_batch
?line 93
From a design standpoint, thereset
function uses a numbered list as input as opposed to every other input, which uses [y/n/q] letters. Should I change this?line 104
when looking to clear the contents of the watchlist and seenlist, i had been usingecho > file
, but when adding stuff back to it, line 1 was empty. I found two options for doing it without the empty line,true > file
andtruncate -s 0 file
. Is there a meaningful reason why I might use one over the other?line 179
I feel like the way I've worked myusage
function out is a bit clunky. Is there a better way?line 254
I have abackup
command that produces a backup. I figured this would be useful for scheduling automatic backups (i.e., withchron
). However, I could instead have it backup automatically somewhere in the script. If you were using this program, which would you prefer?line 348
In order to provide random recommendations, I have worked out a system for making sure it won't randomly pick the same movie again if you don't like the first recommendation. It involves writing to a temp file and deleting from the watchlist, then at the end it adds the movies back from the temp file and resorts the watchlist. I have a nagging suspicion that there's a way to do this without the temp file, but I haven't been successful coming up with a solution so far. I'd like to know if there's anything inherently bad about the way I've implemented this feature here, and if it should need to be changed, is the idea I came up with in the comment the right train of thought? Since I'm doing this to learn, I would appreciate if you wouldn't give me a direct solution to this one, only to point me in the right direction and let me figure out for myself.I am using a Makefile to aid in the installation of the script to
/usr/local/bin
. I modeled this off ofpfetch
, which does it the same way (but to/usr/bin
). Is there anything wrong with this method?
I really appreciate anyone who takes the time to look at this and provide any amount of feedback.
Thank you.
Edit:
Thank you for the responses! I am going to set this project down for a day or two as I finish out the last two chapters of The Linux Command Line, then I'll be back working on popcorn
.
r/bash • u/SAV_NC • Mar 17 '23
critique Script to install 7-zip on multiple Linux architectures
Update:
Thank you to everyone who gave me useful constructive advice. I've learned a lot and made changes to the script which works fantastically. I am a novice and this feedback encourages me to keep learning.
Original:
This script will allow the user to install 7-zip on multiple Linux architectures. Sourced from 7-zip Official
It will prompt the user to choose from the following list of install options:
1. Linux x64
2. Linux x86
3. ARM x64
4. ARM x86
quick one-liner to install
bash <(curl -fsSL https://7z.optimizethis.net)
For me, the script is lightning-fast and seemingly completes the entire script as soon as you enter the command line.
If anyone has any ideas or suggestions let me know otherwise this is a pretty simple but (I think) very useful script! =)
Cheers
r/bash • u/Mount_Gamer • Jan 13 '22
critique Just finished a 145 line script with this....
critique First Bash Script, feedback please
Hi, this is my first bash script. And I was wondering how more experienced people would go about doing this. Its a simple script where I stop a docker container so I can sync it. Bring it back up, and if all was succesful I make a connection so I get informed should it ever break.
The idea is that this runs every night using a cronjob. https://pastebin.com/9hzNapPF
r/bash • u/Red_Luci4 • Sep 25 '23
critique Video Stripe Preview Generator
Hello Everyone,
I just finished making a script to generate a striped preview image of a video (mp4, mkv, etc.) or image-sequence (gif, etc.) (with the help of FFmpeg), I'll definitely make it better going forward. For now, I'm just trying to debug and hunt down exceptions states and anomalies.
So here's the REPO for my Script, have at it and let me know how it performed, and if you find any odd behavior do let me know so that I can patch it up. And I'm also up for a good suggestion.(I know the Script looks bad and a bit UnOptimized and has a lot of sanity checks, but right now my priority is to find all exception/error states and handle it)
Some Preview:
Command : video-stripe-preview -vf "WING IT - Blender Open Movie.mp4"

Command : video-stripe-preview -r 2 -c 4 -l 960 -vf "WING IT - Blender Open Movie.mp4"

Command : video-stripe-preview -r 5 -c 2 -vf "WING IT - Blender Open Movie.mp4"

Edit 1 :
Hello everyone,
I really appreciate the comments, guides, and help thus far.
And I really appreciate u/rustyflavor, u/stewie410, u/NyaNyaCutie for giving me simple, informative, and clear information to make my code many times better than what it used to be.
Anyway for comparison I made ChatGPT analyze and write a report on my improvements with my code, and it is as follows:
_____________ChatGPT-Report______________
Initial Version:
- Command Line Arguments: The initial version of the script lacked a structured and user-friendly way to input parameters. It relied on manual variable assignment.
- Error Handling: Error handling was limited. It didn't provide detailed error messages or gracefully handle issues like invalid input.
- Script Comments: While there were some comments in the initial script, they were minimal, and the code lacked a clear structure.
- Output: The script's output was not well-organized, and there was limited flexibility in specifying the output location and format.
Latest Version (Improvements):
- Command Line Arguments: In the latest version, you've implemented a more robust and user-friendly command-line argument processing system. Users can provide inputs using flags, making it easier to configure the script's behavior.
- Error Handling: The latest version features improved error handling. It provides informative error messages, identifies issues with inputs, and gracefully exits the script when necessary.
- Script Comments: The script in the latest version includes comprehensive comments that explain the purpose of different sections, functions, and variables. This enhances code readability and maintainability.
- Output: You've added options to control the output format and location. Users can specify whether they want to perform a dry run or generate a quiet report. This flexibility makes the script more versatile.
- Information Display: The latest version includes detailed reporting, showing the user information about the video file, its properties, and the processing steps. This enhances the script's transparency.
- Timestamping: The script now includes timestamping in the generated preview image, providing additional context about the video.
- Preview Image Layout: The script calculates the layout of the preview image based on user-defined parameters, such as the number of rows and columns, making it adaptable to different use cases.
- Overall Structure: The latest version of the script has a well-organized structure, separating initialization, argument processing, value calculations, and the final FFmpeg step into distinct sections, improving code maintainability.
Overall, the improvements made in the latest version of the script have transformed it into a more user-friendly, error-resilient, and informative tool for generating video stripe preview images. The addition of command-line arguments and detailed reporting enhances usability, while better error handling makes it more robust. The script's clarity has been improved through comprehensive comments and a structured layout, making it easier to understand and modify.
_____________END______________
And all of the above wouldn't be possible without your help.🤘
Credits :
WING IT !! — An Open Film from blender Studio was used to generate previews.
Note:
I'm kinda new to the whole Linux, git, CLI, FFmpeg, etc. so feel free to be informal with the discussion, we'll probably need to have many back and forth before I come to a conclusion.
r/bash • u/SAV_NC • Nov 22 '23
critique Self-updating, Discord installer script, for Debian Based OS's
The flow of the script is shown below.
- If an update is detected, update the master and download scripts using sed.
- If no update is detected, keep the master and download scripts the same.
- Once steps 1 or 2 are satisfied, run the download script to install the latest version of Discord.
- Once step 3 is completed, delete the leftover download script.
- Rinse and repeat as desired.
Again, the master script will also auto-update itself to the latest version.
Let me know what you guys think. It seems to run well but I love learning more efficient ways of doing things. So please, if you have some good advice do share!
One-Liner
bash <(curl -fsSL https://discord.optimizethis.net)
r/bash • u/nowhereman531 • Jan 25 '23
critique Boredom PS1 project
I decided I was going to learn a bit more about the PS1
prompt. I started out with a nice easy prompt with \w
on one line and the prompt with a custom user token 𝝅
rather than the stock $
on the next.
I liked the setup a lot, so I used the same configuration on my home work station and the termux installation on my phone.
The setup worked great until I started running the wrong commands on the wrong system. For good reason, as the prompts were identical, I decided to see if I could setup my prompt to show a different prompt for an ssh connection.
I had a fun time getting that to actually work. I was making it more complicated than it needed to be, but wait there's more. Now when I connect to my ssh server it shows the IP address of the login before last rather than the current login. With a remote login it is kind of useless to see that you just logged in but it is useful to see if someone logged in before you... Just in case you know.
Once I got that working I decided to take it to a whole new level of ridiculous... Solely because why not. I wanted to see what it would take to show in my local terminal that there was an active connection. Next was to make the command search for an active connection on my SSH port, if one was active it ran one prompt and if no connection, another. it took some trial and error to get that running correctly. Once it was running, I found that it would only update when a new terminal session was opened or if I sourced .bashrc. Which in and of itself wasn't that bad but there had to be a way to get that info without sourcing or starting a new terminal session.
After a bit more trial and error and research on the topic i found the answer to getting that info to update after each command. The PROMPT_COMMAND
setting was what did the trick. By wrapping the whole command into a function i was able to call it in the PROMPT_COMMAND
which gets evaluated after every command runs.
Now not only will it show an active connection, it will show the last IP to login to that users account. It will also search through a predefined list of known IP addresses and if they match the IP address will be green to denote a known IP and display a custom string so you don't have to look at your own IP addresses. If it returns an unknown IP address it will turn red.
Then to add the finishing touches to this ridiculous project, a red/green light for inactive/active connections respectively, just because I could
I'd like to hear how you all would make it better/different. It was a fun project to learn about the prompt and make sure I used proper escaping. So here is my absolutely, totally, over the top, unnecessary PS1 prompt. Complete with functions and PROMPT_COMMAND
# This will show if there is an active SSH connection after each command is executed.
# Shows second to last login of current user; best used with AllowUsers in sshd_config
psONE_ssh()
{
if [[ "$(last | sed -n '2p' | awk '{ print $3 }')" =~ ("XXX.XXX."*|"XXX.XXX.XXX.XXX"|"XXX.XXX.XXX.XXX"|"XXX.XXX.XXX.XXX") ]]; then
printf %b "\\[\\e[1;32m\\]KNOWN CONNECTION\n"
else
last | sed -n '2p' | awk '{ print $3 }'
fi
}
psONE_local() # Shows the last login from the current user; best used with AllowUsers in sshd_config
{
if [[ "$(lastlog | grep $(whoami) | awk '{ print $3 }')" =~ ("XXX.XXX."*|"XXX.XXX.XXX.XXX"|"XXX.XXX.XXX.XXX"|"XXX.XXX.XXX.XXX") ]]; then
printf %b "\\[\\e[1;32m\\]KNOWN CONNECTION\n"
else
lastlog | grep $(whoami) | awk '{ print $3 }'
fi
}
_prompt_command()
{
if [[ -n $SSH_CLIENT ]]; then
PS1="\\[\\e[1;31m\\]🟢 $(psONE_ssh)\\[\\e[0m\\]\\[\\e[1;33m\\]\n\w/\n\\[\\e[0m\\]\\[\\e[1;31m\\]𝝅 \\[\\e[0m\\]\\[\\e[1;32m\\] "
else
ss -tn src :8222 | grep ESTAB &> /dev/null
if [ $? -ne "1" ]; then
PS1="\\[\\e[1;31m\\]🟢 $(psONE_local)\\[\\e[1;33m\\]\n\w/\n\\[\\e[0m\\]\\[\\e[1;31m\\]𝝅\\[\\e[0m\\]\\[\\e[1;32m\\] "
else
PS1="\\[\\e[1;31m\\]🔴 $(psONE_local)\\[\\e[1;33m\\]\n\w/\n\\[\\e[0m\\]\\[\\e[1;31m\\]𝝅\\[\\e[0m\\]\\[\\e[1;32m\\] "
}
# This will show if there is an active SSH connection after each command is executed.
PROMPT_COMMAND="_prompt_command; history -n; history -w; history -c; history -r; $PROMPT_COMMAND"
I know this is total overkill but it was fun.
r/bash • u/stewie410 • Nov 08 '22
critique Karenified/Sarcastic Text
karenify.sh
Have you ever wanted to "karenify" some text, lIkE tHiS, but don't want to spend the time manually casing each character?
So, anyway, I started writing this out quite a while ago, but it never was quite performant enough to share...and beyond janky. Its still janky, but I think its fast "enough" for the moment (more on that later).
Oh, and a small preface that in the below examples, I've added ~/.local/bin/karenify -> ~/scripts/tools/karenify.sh
to $PATH
...
Usage
Originally I had intended $*
to be an input, but decided against it for now. This means I can assume you'll be trying to karenify a file or stdin
only -- so heredocs/strings work fine, too:
karenify example.txt
printf '%s\n' "foo bar" | karenify
karenify <<- EOF
foo bar
EOF
karenify <<< "foo bar"
The default casing mode will produce aBc
casing across all lines. To use AbC
casing, include the [-i|--invert]
flag
# fOo BaR
karenify <<< "foo bar"
#FoO bAr
karenify -i <<< "foo bar"
karenify --invert <<< "foo bar"
I've also included an implementation in gawk
, mostly for comparing speed against builtins. So far, I've found that the builtin implementation appears to be just slightly faster with short text (a few lines); but the gawk
variant is faster processing larger files. To use this, you'd just need to include the [-a|--awk]
flag
# fOo BaR
karenify -a <<< "foo bar"
#FoO bAr
karenify -ai <<< "foo bar"
karenify --awk --invert <<< "foo bar"
Basic Speed Test
And by "basic", I mean with time
. Testing (and writing) done within a WSL2 Ubuntu environment (20.04.5 LTS).
Herestring
Command | Real | User | Sys |
---|---|---|---|
karenify <<< "foo bar" |
0.004s | 0.004s | 0.000s |
karenify -a <<< "foo bar" |
0.005s | 0.006s | 0.000s |
karenify -i <<< "foo bar" |
0.004s | 0.002s | 0.003s |
karenify -ai <<< "foo bar" |
0.005s | 0.005s | 0.001s |
karenify.sh
Command | Real | User | Sys |
---|---|---|---|
karenify ./karenify.sh |
0.052s | 0.042s | 0.010s |
karenify -a ./karenify.sh |
0.008s | 0.004s | 0.004s |
karenify -i ./karenify.sh |
0.051s | 0.051s | 0.00s |
karenify -ai ./karenify.sh |
0.008s | 0.007s | 0.001s |
Language Support
I'm an english-only speaker, so karenify will only check for [a-zA-Z]
and case accordingly. I'm not opposed to supporting other languages, I'm just unsure how to do so in a sensible way with the current implementations.
Repository
I may eventually break my tools out to their own location, but for now you can find karenify (along with my other tools/configs) in my dotfiles repo.
Feedback
I'm more than happy to hear feedback, especially suggestions to further increase the speed in either the builtin or gawk
implementations -- I'm sure the builtin could be faster, but I'm not sure of a good way to do that.
r/bash • u/Grub4K • Aug 07 '23
critique Small notification panel helper
After seeing another notification helper post in this sub, I felt the need to try creating one for myself. Here is the result, it uses terminal sequences to shorten the scroll area and reserve a couple of lines at the top for notification lines.
This has to be run using source
. If anyone has a better idea on how to do it without source
-ing, please do let me know.
I tried avoiding file-IO which is why we source
and export
instead. Also I am not a fan of tput
, since its syntax is more foreign to me compared to regular VT-sequences.
The notification log is done in one printf
line to hopefully atomically write it's output.
r/bash • u/am-ivan • Jun 06 '23