---
title: "Essential Bash Variables for Every Script"
lang: "en"
author: "Mohammad Abu Mattar"
canonical: https://mkabumattar.com/post/essential-bash-variables
---

![Blog post image for Essential Bash Variables for Every Script - Master the most useful Bash special parameters and environment variables. Learn how to use $0, $?, $@, $UID, $EUID, and XDG variables to write more reliable and portable scripts.](/_astro/hero.B4bDowyY_ZfzwTY.webp)

[Home](/)›[Codesnippets](/codesnippets)›[All Categories](/codesnippets/categories)›[Shell scripting](/codesnippets/categories/shell-scripting)

Codesnippets

[Prev in Shell scriptingCheck S3 Bucket Existence](/codesnippets/post/bash-s3-bucket-exists)[Next in Shell scriptingWhy printf Beats echo in Linux Scripts](/codesnippets/post/printf-beats-echo-linux-scripts)

[Shell scripting](/codesnippets/categories/shell-scripting)[Devops](/codesnippets/categories/devops)[Bash](/codesnippets/bash)

# Essential Bash Variables for Every Script

[Mohammad Abu Mattar](/authors/mohammad-abu-mattar)Published: 26 Dec 202508 Mins read06 Mins listen

[Markdown for AI(opens in a new tab)](/post/essential-bash-variables/index.md "Open the plain-Markdown version of this page, for pasting into an AI tool")

TL;DR

Master the most useful Bash special parameters and environment variables. Learn how to use $0, $?, $@, $UID, $EUID, and XDG variables to write more reliable and portable scripts.

Series

[Linux & System Administration](/series/linux--system-administration)1/1

All posts in this series (1)

Code Snippets1

1.  [Essential Bash Variables for Every ScriptYou are here](/codesnippets/post/essential-bash-variables)

### Essential Bash Variables for Every Script

Contents

[Overview](#overview)[The problem with hard-coded paths](#the-problem-with-hard-coded-paths)[The solution: built-in Bash variables](#the-solution-built-in-bash-variables)[Key Bash variables summary](#key-bash-variables-summary)[Special parameters](#special-parameters)[Get the script path](#get-the-script-path)[Check exit status](#check-exit-status)[Access script arguments](#access-script-arguments)[Environment variables](#environment-variables)[Get user ID](#get-user-id)[Use the XDG directory specification](#use-the-xdg-directory-specification)[Complete example: production-ready script](#complete-example-production-ready-script)[Quick reference](#quick-reference)[Best practices](#best-practices)[Do these things](#do-these-things)[Avoid these mistakes](#avoid-these-mistakes)[References](#references)

## [Overview](#overview)

**Quick Tip**

You know what’s worse than writing scripts? Writing scripts that break every time you move them to a different machine. Built-in Bash variables fix that.

## [The problem with hard-coded paths](#the-problem-with-hard-coded-paths)

We’ve all been there. You hard-code `/home/john/.config` in your script, and it works great on your laptop. Then you run it on the server, and everything breaks because the server uses a different username or directory structure. When you’ve got dozens (or hundreds) of scripts, tracking down all these hard-coded values becomes a real headache.

## [The solution: built-in Bash variables](#the-solution-built-in-bash-variables)

Bash already knows about your system. It’s got built-in variables for script paths, user IDs, home directories, and more. Instead of guessing or hard-coding, just ask Bash. Your scripts will work everywhere without modification.

## [Key Bash variables summary](#key-bash-variables-summary)

**TL;DR**

-   Use `$BASH_SOURCE` (or `$0`) to get the script path reliably
-   Check exit codes with `$?` to handle errors properly
-   Access arguments with `$1`, `$2`, `$@`, and `$*`
-   Get user IDs with `$UID` and `$EUID` for permission checks
-   Use XDG variables for standard user directories instead of hard-coding paths

## [Special parameters](#special-parameters)

### [Get the script path](#get-the-script-path)

Sometimes you need to know where your script lives. Maybe you’re building a help menu and want to show the script name, or you need to reference files relative to the script’s location. Here’s how you grab that info.

get\_script\_path.sh

```
1#!/usr/bin/env bash2
3# $BASH_SOURCE gives you the full path to this script4SCRIPT_PATH="$BASH_SOURCE"5echo "Full path: $SCRIPT_PATH"6# Output: /home/user/scripts/my_script.sh7
8# Use basename to strip the directory and keep just the filename9SCRIPT_NAME="$(basename "$BASH_SOURCE")"10echo "Script name: $SCRIPT_NAME"11# Output: my_script.sh12
13# Here's a practical use case: building a help menu14cat <<EOF15Usage: $SCRIPT_NAME [OPTIONS]16
17Options:18  -h, --help     Show this help message19  -v, --version  Show version information20EOF
```

  

Tip

There’s also `$0`, which works similarly but has a quirk. If someone sources your script (like `source my_script.sh`), `$0` returns “bash” instead of the script name. `$BASH_SOURCE` doesn’t have this issue, so use that if you’re writing Bash-specific code.

### [Check exit status](#check-exit-status)

When a command finishes, it leaves behind an exit code, a kind of status report. If everything went fine, you get `0`. If something went wrong, you get a number between `1` and `255`. The variable `$?` holds this exit code, and you can use it to figure out what happened and respond accordingly.

check\_exit\_status.sh

```
1#!/usr/bin/env bash2
3# Method 1: Explicit check using $?4ls /nonexistent_directory5if [[ $? -ne 0 ]]; then6  echo "Error: Directory does not exist"7  exit 18fi9
10# Method 2: Cleaner approach test the command directly11# If ls succeeds, run the 'then' block. If it fails, run 'else'12if ls /home; then13  echo "Directory exists"14else15  echo "Directory does not exist"16fi17
18# Method 3: One-liner with logical operators19# && means "run this if the previous command succeeded"20# || means "run this if the previous command failed"21ls /home && echo "Success!" || echo "Failed!"22
23# Method 4: Handle specific error codes24# Some commands return different numbers for different errors25grep "pattern" file.txt26case $? in27  0) echo "Pattern found";;28  1) echo "Pattern not found";;29  2) echo "File error or syntax problem";;30  *) echo "Unknown error";;31esac
```

  

Important

Here’s the catch. `$?` only remembers the last command. If you run another command, the old exit code is gone. So if you need it later, save it right away:

Terminal window

```
1some_command2exit_code=$?  # Save it now!3echo "Did some other stuff"4# Now we can still check the original exit code5if [[ $exit_code -ne 0 ]]; then6  echo "Original command failed"7fi
```

### [Access script arguments](#access-script-arguments)

You’ll want your scripts to accept arguments: filenames, options, or configuration values. Bash makes this pretty straightforward, though the syntax looks a bit weird at first.

handle\_arguments.sh

```
1#!/usr/bin/env bash2
3# Individual arguments are numbered: $1, $2, $3, etc.4echo "First argument: $1"5echo "Second argument: $2"6echo "Third argument: $3"7# Run like: ./script.sh hello world test8# Output: hello, world, test9
10# Count how many arguments were passed11echo "Total arguments: ${#@}"12
13# Loop through all arguments14# $@ treats each argument separately, which is usually what you want15echo -e "\nProcessing all arguments:"16for arg in "$@"; do17  echo "  - $arg"18done19
20# The difference between $@ and $*21# This matters when your arguments contain spaces22function demo_at {23  # Each argument stays separate24  printf '@: [%s]\n' "$@"25}26
27function demo_star {28  # All arguments merge into one string29  printf '*: [%s]\n' "$*"30}31
32echo -e "\nDifference between \$@ and \$*:"33demo_at "arg one" "arg two"    # Prints: @: [arg one] and @: [arg two]34demo_star "arg one" "arg two"  # Prints: *: [arg one arg two] (all together)35
36# Real-world example: A function that processes files37function process_files() {38  # First, make sure we got at least one file39  if [[ ${#@} -eq 0 ]]; then40    echo "Error: No files specified"41    echo "Usage: process_files file1 file2 ..."42    return 143  fi44
45  # Process each file46  for file in "$@"; do47    if [[ -f "$file" ]]; then48      echo "Processing: $file"49      # Your actual file processing logic goes here50      # wc -l "$file"  # Example: count lines51    else52      echo "Warning: File not found: $file"53    fi54  done55}56
57# You'd call it like this:58# process_files report.txt data.csv notes.md
```

  

Tip

Always use quotes around `"$@"`. If you don’t, filenames with spaces will break. For example, without quotes, `"my file.txt"` becomes two separate arguments: `"my"` and `"file.txt"`. With quotes, it stays as one argument.

## [Environment variables](#environment-variables)

### [Get user ID](#get-user-id)

Sometimes you need to know who’s running your script. Maybe you’re creating user-specific temp files, or you need to check if someone’s running as root. That’s where `$UID` and `$EUID` come in.

check\_user\_permissions.sh

```
1#!/usr/bin/env bash2
3# Root check: A common pattern for admin scripts4# Root user always has UID 05if [[ $EUID -eq 0 ]]; then6  echo "Running with root privileges"7  # Safe to do system-level stuff here8else9  echo "Running as regular user (UID: $UID)"10  echo "Some operations may require sudo"11  # Maybe prompt for sudo, or just warn and continue12fi13
14# Build paths specific to the current user15# This is useful for multi-user systems16USER_CACHE_DIR="/run/user/$UID/cache"17echo "User cache directory: $USER_CACHE_DIR"18# Example: /run/user/1000/cache19
20# Practical example: Create a temp directory that's unique per user21# This prevents conflicts when multiple users run your script22function create_user_temp() {23  local temp_dir="/tmp/myapp-$UID"24
25  if [[ ! -d "$temp_dir" ]]; then26    mkdir -p "$temp_dir"27    echo "Created temp directory: $temp_dir"28  fi29
30  echo "$temp_dir"31}32
33# Now each user gets their own isolated temp space34TEMP_DIR=$(create_user_temp)35echo "Using temp directory: $TEMP_DIR"36# User 1000: /tmp/myapp-100037# User 1001: /tmp/myapp-1001
```

  

Note

You might be wondering about the difference between `$UID` and `$EUID`. For most scripts, they’re the same. They only differ in weird edge cases involving `sudo` or special setuid programs. When in doubt, use `$EUID` for permission checks. That is the one that matters.

### [Use the XDG directory specification](#use-the-xdg-directory-specification)

Where should your script save config files? Or cache data? Or store downloaded files? You might think “just use `~/.config`” but what if a user wants to organize things differently? That’s where XDG variables come in. They’re the standard way Linux systems handle user directories.

use\_xdg\_paths.sh

```
1#!/usr/bin/env bash2
3# Set XDG variables if they're not already set4# The syntax ${VAR:=default} means "use VAR if it exists, otherwise use default"5export "${XDG_CONFIG_HOME:=$HOME/.config}"        # Config files6export "${XDG_CACHE_HOME:=$HOME/.cache}"          # Temporary cache data7export "${XDG_DATA_HOME:=$HOME/.local/share}"    # Application data8export "${XDG_STATE_HOME:=$HOME/.local/state}"   # State files (logs, history, etc.)9
10# Now build your app's specific directories11APP_NAME="myapp"12APP_CONFIG_DIR="$XDG_CONFIG_HOME/$APP_NAME"  # ~/.config/myapp13APP_CACHE_DIR="$XDG_CACHE_HOME/$APP_NAME"    # ~/.cache/myapp14APP_DATA_DIR="$XDG_DATA_HOME/$APP_NAME"      # ~/.local/share/myapp15
16# Create these directories if they don't exist yet17function initialize_app_directories() {18  mkdir -p "$APP_CONFIG_DIR"19  mkdir -p "$APP_CACHE_DIR"20  mkdir -p "$APP_DATA_DIR"21
22  echo "Initialized application directories:"23  echo "  Config: $APP_CONFIG_DIR"24  echo "  Cache:  $APP_CACHE_DIR"25  echo "  Data:   $APP_DATA_DIR"26}27
28initialize_app_directories29
30# Example: Save settings to the config directory31function save_config() {32  local config_file="$APP_CONFIG_DIR/settings.conf"33
34  cat > "$config_file" <<EOF35# Application settings36debug_mode=false37log_level=info38max_connections=10039EOF40
41  echo "Saved config to: $config_file"42}43
44# Example: Load settings from the config directory45function load_config() {46  local config_file="$APP_CONFIG_DIR/settings.conf"47
48  if [[ -f "$config_file" ]]; then49    # Source the config file to load variables50    source "$config_file"51    echo "Loaded config from: $config_file"52    echo "Debug mode: $debug_mode"53    echo "Log level: $log_level"54  else55    echo "Config file not found: $config_file"56    return 157  fi58}59
60save_config61load_config
```

  

Tip

This respects how users organize their systems, not just the spec. Some people put config files on a separate partition, or use custom paths for backups. By using XDG variables, your script just works in all these scenarios.

## [Complete example: production-ready script](#complete-example-production-ready-script)

Here’s what a script looks like when you use all these variables properly. It’s got error handling, logging, argument processing, and follows XDG standards. Use it as a template for your own scripts.

production\_script.sh

```
1#!/usr/bin/env bash2
3# Strict mode: exit on errors, undefined variables, and pipe failures4set -euo pipefail5
6# Set up XDG directories with sensible defaults7export "${XDG_CONFIG_HOME:=$HOME/.config}"8export "${XDG_CACHE_HOME:=$HOME/.cache}"9export "${XDG_DATA_HOME:=$HOME/.local/share}"10
11# Grab script info using the variables we learned about12SCRIPT_NAME="$(basename "$BASH_SOURCE")"13SCRIPT_DIR="$(cd "$(dirname "$BASH_SOURCE")" && pwd)"14APP_NAME="myapp"15
16# Build our application's directory structure17APP_CONFIG_DIR="$XDG_CONFIG_HOME/$APP_NAME"18APP_CACHE_DIR="$XDG_CACHE_HOME/$APP_NAME"19APP_LOG_FILE="$APP_CACHE_DIR/app.log"20
21# ANSI color codes for pretty output22RED='\033[0;31m'23GREEN='\033[0;32m'24YELLOW='\033[1;33m'25NC='\033[0m'  # Reset to no color26
27# Simple logging function with timestamps28# Usage: log "INFO" "Something happened"29function log() {30  local level="$1"31  shift32  local message="$*"33  local timestamp=$(date '+%Y-%m-%d %H:%M:%S')34
35  # Print to screen AND save to log file36  echo "[$timestamp] [$level] $message" | tee -a "$APP_LOG_FILE"37}38
39# Centralized error handling40# This logs the error and exits with a non-zero status41function error_exit() {42  log "ERROR" "$*" >&243  exit 144}45
46# Check if we have everything we need to run47function check_prerequisites() {48  # Example: Some scripts need root privileges49  if [[ $EUID -ne 0 ]]; then50    error_exit "This script must be run as root (current UID: $UID)"51  fi52
53  # Verify required commands are installed54  local required_commands=("curl" "jq" "aws")55  for cmd in "${required_commands[@]}"; do56    if ! command -v "$cmd" &> /dev/null; then57      error_exit "Required command not found: $cmd. Please install it first."58    fi59  done60
61  log "INFO" "All prerequisites satisfied"62}63
64# Set up directories and initialize the app65function initialize() {66  # Create necessary directories67  mkdir -p "$APP_CONFIG_DIR" "$APP_CACHE_DIR"68  touch "$APP_LOG_FILE"69
70  # Log some useful info for debugging71  log "INFO" "Initialized $APP_NAME"72  log "INFO" "Script: $SCRIPT_NAME (located at $SCRIPT_DIR)"73  log "INFO" "User: $USER (UID: $UID)"74}75
76# Parse command-line arguments77function process_arguments() {78  # If no arguments, show help and exit79  if [[ ${#@} -eq 0 ]]; then80    cat <<EOF81Usage: $SCRIPT_NAME [OPTIONS] [FILES...]82
83Options:84  -h, --help     Show this help message85  -v, --verbose  Enable verbose logging86  -d, --debug    Enable debug mode87
88Examples:89  $SCRIPT_NAME file1.txt file2.txt90  $SCRIPT_NAME --verbose *.log91EOF92    exit 093  fi94
95  # Set up some flags96  local verbose=false97  local debug=false98  local files=()99
100  # Loop through all arguments101  while [[ $# -gt 0 ]]; do102    case "$1" in103      -h|--help)104        process_arguments  # Recursively call to show help105        ;;106      -v|--verbose)107        verbose=true108        log "INFO" "Verbose mode enabled"109        shift110        ;;111      -d|--debug)112        debug=true113        set -x  # This makes Bash print every command before running it114        shift115        ;;116      -*)117        error_exit "Unknown option: $1"118        ;;119      *)120        # Anything that doesn't start with - is treated as a file121        files+=("$1")122        shift123        ;;124    esac125  done126
127  log "INFO" "Processing ${#files[@]} file(s)"128
129  # Process each file130  for file in "${files[@]}"; do131    if [[ -f "$file" ]]; then132      log "INFO" "Processing file: $file"133      # Your actual file processing logic would go here134      # Example: wc -l "$file"135    else136      log "WARN" "File not found: $file"137    fi138  done139}140
141# Main entry point142function main() {143  initialize144  check_prerequisites || exit $?145  process_arguments "$@" || exit $?146
147  log "INFO" "Script completed successfully"148}149
150# This is where everything starts151# We pass all command-line arguments to main using "$@"152main "$@"
```

## [Quick reference](#quick-reference)

Variable

Description

Example

`$0` or `$BASH_SOURCE`

Script path

`/home/user/script.sh`

`$(basename $0)`

Script name only

`script.sh`

`$?`

Exit status of last command

`0` (success) or `1-255` (error)

`$1`, `$2`, `$3`…

Positional parameters

First, second, third argument

`$@`

All arguments as array

Each argument separate

`$*`

All arguments as string

All arguments in one string

`${#@}`

Number of arguments

`3`

`$UID`

Real user ID

`1000`

`$EUID`

Effective user ID

`0` (when using sudo)

`$USER`

Username

`john`

`$HOME`

Home directory

`/home/john`

`$XDG_CONFIG_HOME`

Config directory

`~/.config`

`$XDG_CACHE_HOME`

Cache directory

`~/.cache`

`$XDG_DATA_HOME`

Data directory

`~/.local/share`

## [Best practices](#best-practices)

### [Do these things](#do-these-things)

-   **Always quote your variables:** Use `"$var"` instead of `$var`. This prevents weird issues when variables contain spaces or special characters.
-   **Set defaults for XDG variables:** Use `${XDG_CONFIG_HOME:=$HOME/.config}` so your script works even if the variable isn’t set.
-   **Prefer `$BASH_SOURCE` over `$0`:** It’s more reliable, especially when your script might be sourced instead of executed.
-   **Check exit codes for important operations:** Don’t just assume things worked. Check `$?` or use `if` statements.
-   **Quote `"$@"` when passing arguments:** This preserves spaces in filenames and arguments.

### [Avoid these mistakes](#avoid-these-mistakes)

-   **Don’t hard-code paths:** Never write `/home/john/.config` directly. Use variables so your script works for everyone.
-   **Don’t use `$*` by default:** It merges all arguments into one string, which usually isn’t what you want. Stick with `"$@"`.
-   **Don’t assume `$?` sticks around:** It changes with every command. Save it immediately if you need it later.
-   **Don’t forget to quote path variables:** Unquoted variables break when paths have spaces.
-   **Don’t use `$UID` for permission checks:** Use `$EUID` instead. That is what actually matters for access control.

### [References](#references)

-   [GNU Bash Manual - Special Parameters](https://www.gnu.org/software/bash/manual/html_node/Special-Parameters.html)
-   [XDG Base Directory Specification](https://specifications.freedesktop.org/basedir/latest/)
-   [Advanced Bash-Scripting Guide](https://tldp.org/LDP/abs/html/)

Was this useful?

## Tags

[#Bash](/codesnippets/tags/bash)[#Shell Scripting](/codesnippets/tags/shell-scripting)[#Linux](/codesnippets/tags/linux)[#DevOps](/codesnippets/tags/devops)[#Automation](/codesnippets/tags/automation)[#Environment Variables](/codesnippets/tags/environment-variables)[#POSIX](/codesnippets/tags/posix)

## Share

[Facebook](https://facebook.com/sharer/sharer.php?u=https%3A%2F%2Fmkabumattar.com%2Fcodesnippets%2Fpost%2Fessential-bash-variables "Share on Facebook")[Twitter](https://twitter.com/intent/tweet/?text=Essential%20Bash%20Variables%20for%20Every%20Script&url=https%3A%2F%2Fmkabumattar.com%2Fcodesnippets%2Fpost%2Fessential-bash-variables "Share on Twitter")[LinkedIn](https://www.linkedin.com/shareArticle?mini=true&url=https%3A%2F%2Fmkabumattar.com%2Fcodesnippets%2Fpost%2Fessential-bash-variables&title=Essential%20Bash%20Variables%20for%20Every%20Script&summary=Master%20the%20most%20useful%20Bash%20special%20parameters%20and%20environment%20variables.%20Learn%20how%20to%20use%20%240%2C%20%24%3F%2C%20%24%40%2C%20%24UID%2C%20%24EUID%2C%20and%20XDG%20variables%20to%20write%20more%20reliable%20and%20portable%20scripts.&source=https://mkabumattar.com "Share on LinkedIn")[WhatsApp](https://wa.me/?text=Essential%20Bash%20Variables%20for%20Every%20Script%20https%3A%2F%2Fmkabumattar.com%2Fcodesnippets%2Fpost%2Fessential-bash-variables "Share on WhatsApp")[Telegram](https://t.me/share/url?url=https%3A%2F%2Fmkabumattar.com%2Fcodesnippets%2Fpost%2Fessential-bash-variables&text=Essential%20Bash%20Variables%20for%20Every%20Script "Share on Telegram")[Reddit](https://www.reddit.com/submit?url=https%3A%2F%2Fmkabumattar.com%2Fcodesnippets%2Fpost%2Fessential-bash-variables&title=Essential%20Bash%20Variables%20for%20Every%20Script "Share on Reddit")[Hacker News](http://news.ycombinator.com/submitlink?u=https%3A%2F%2Fmkabumattar.com%2Fcodesnippets%2Fpost%2Fessential-bash-variables&t=Essential%20Bash%20Variables%20for%20Every%20Script "Share on Hacker News")[Pinterest](https://pinterest.com/pin/create/button/?url=https%3A%2F%2Fmkabumattar.com%2Fcodesnippets%2Fpost%2Fessential-bash-variables&media=&description=Master%20the%20most%20useful%20Bash%20special%20parameters%20and%20environment%20variables.%20Learn%20how%20to%20use%20%240%2C%20%24%3F%2C%20%24%40%2C%20%24UID%2C%20%24EUID%2C%20and%20XDG%20variables%20to%20write%20more%20reliable%20and%20portable%20scripts. "Share on Pinterest")[Email](<mailto:?subject=Essential%20Bash%20Variables%20for%20Every%20Script&body=Check out this article: https%3A%2F%2Fmkabumattar.com%2Fcodesnippets%2Fpost%2Fessential-bash-variables>)

## Comments

## You might also enjoy

More posts on similar topics

[![Why printf Beats echo in Linux Scripts](/_astro/hero.Dl3YkIwZ_Z1w9hux.webp)](/codesnippets/post/printf-beats-echo-linux-scripts)

## [Why printf Beats echo in Linux Scripts](/codesnippets/post/printf-beats-echo-linux-scripts)

-   [Mohammad Abu Mattar](/authors/mohammad-abu-mattar)
-   [Shell scripting](/codesnippets/categories/shell-scripting)
-   [Devops](/codesnippets/categories/devops)
-   [Linux](/codesnippets/categories/linux)

Scripting Tip A script that works on your machine can produce different output on another system. The output command is often the reason. printf behaves the same way across shells, and echo d

[#Bash](/codesnippets/tags/bash)[#Shell Scripting](/codesnippets/tags/shell-scripting)[#Printf](/codesnippets/tags/printf)+5 tags

[read more](/codesnippets/post/printf-beats-echo-linux-scripts)

[![Check S3 Bucket Existence](/_astro/hero.CWiO4GWV_1YUYTb.webp)](/codesnippets/post/bash-s3-bucket-exists)

## [Check S3 Bucket Existence](/codesnippets/post/bash-s3-bucket-exists)

-   [Mohammad Abu Mattar](/authors/mohammad-abu-mattar)
-   [Aws](/codesnippets/categories/aws)
-   [Shell scripting](/codesnippets/categories/shell-scripting)
-   [Devops](/codesnippets/categories/devops)

Quick Tip Don't let your deployment blow up because of a missing S3 bucket. This Bash script lets you check if a bucket exists before anything fails. The Problem Missing bucket failure

[#Bash](/codesnippets/tags/bash)[#AWS](/codesnippets/tags/aws)[#DevOps](/codesnippets/tags/devops)+3 tags

[read more](/codesnippets/post/bash-s3-bucket-exists)

[![Bash Retry Function: Automatically Retry Failing Commands with Exponential Backoff](/_astro/hero.Dap62rVN_Z1q0nar.webp)](/codesnippets/post/bash-retry-function-exponential-backoff)

## [Bash Retry Function: Automatically Retry Failing Commands with Exponential Backoff](/codesnippets/post/bash-retry-function-exponential-backoff)

-   [Mohammad Abu Mattar](/authors/mohammad-abu-mattar)
-   [Devops](/codesnippets/categories/devops)
-   [Shell scripting](/codesnippets/categories/shell-scripting)
-   [Automation](/codesnippets/categories/automation)

Quick Tip Wrap any flaky command in one reusable retry function and stop re-running red pipelines by hand. The Problem The Problem Some commands fail for reasons that have nothing to

[#Bash](/codesnippets/tags/bash)[#Retry](/codesnippets/tags/retry)[#Exponential Backoff](/codesnippets/tags/exponential-backoff)+3 tags

[read more](/codesnippets/post/bash-retry-function-exponential-backoff)

[![Per-App Shell History for Bash](/_astro/hero.Da_6jPH6_Z1EorRD.webp)](/codesnippets/post/bash-per-app-history)

## [Per-App Shell History for Bash](/codesnippets/post/bash-per-app-history)

-   [Mohammad Abu Mattar](/authors/mohammad-abu-mattar)
-   [Shell scripting](/codesnippets/categories/shell-scripting)
-   [Productivity](/codesnippets/categories/productivity)

Organize your Bash history per terminal app. Ever jumped between iTerm2, Ghostty, and VS Code's terminal only to have your command history get all mixed up? This Bash snippet keeps things clean b

[#Bash](/codesnippets/tags/bash)[#Shell Scripting](/codesnippets/tags/shell-scripting)[#Productivity](/codesnippets/tags/productivity)+3 tags

[read more](/codesnippets/post/bash-per-app-history)

[![AWS EC2 Instance Management with Boto3: Start, Stop, and Query Instances](/_astro/hero.PnHlvJay_ZkFqWG.webp)](/codesnippets/post/aws-ec2-instance-management-boto3-python)

## [AWS EC2 Instance Management with Boto3: Start, Stop, and Query Instances](/codesnippets/post/aws-ec2-instance-management-boto3-python)

-   [Mohammad Abu Mattar](/authors/mohammad-abu-mattar)
-   [Cloud](/codesnippets/categories/cloud)
-   [Aws](/codesnippets/categories/aws)
-   [Devops](/codesnippets/categories/devops)
-   [Automation](/codesnippets/categories/automation)

If you've ever spent 20 minutes clicking through the AWS Console just to stop a handful of dev instances, you already know the pain. It's tedious, it doesn't scale, and one wrong click can ruin your a

[#AWS](/codesnippets/tags/aws)[#EC2](/codesnippets/tags/ec2)[#Boto3](/codesnippets/tags/boto3)+6 tags

[read more](/codesnippets/post/aws-ec2-instance-management-boto3-python)

[![Per-App Shell History for Zsh](/_astro/hero.DRenzVy__1xwzSL.webp)](/codesnippets/post/zsh-per-app-history)

## [Per-App Shell History for Zsh](/codesnippets/post/zsh-per-app-history)

-   [Mohammad Abu Mattar](/authors/mohammad-abu-mattar)
-   [Shell scripting](/codesnippets/categories/shell-scripting)
-   [Productivity](/codesnippets/categories/productivity)

Organize your shell history per terminal app. Ever jumped between iTerm2, Ghostty, and VS Code's terminal only to have your command history get all mixed up? This Zsh snippet keeps things clean b

[#Zsh](/codesnippets/tags/zsh)[#Shell Scripting](/codesnippets/tags/shell-scripting)[#Productivity](/codesnippets/tags/productivity)+3 tags

[read more](/codesnippets/post/zsh-per-app-history)

6 related posts
