Skip to content

Instantly share code, notes, and snippets.

@scruffydan
Last active September 10, 2025 00:12
Show Gist options
  • Select an option

  • Save scruffydan/41ba5881fbc0bdc9d1c1823c087c70f7 to your computer and use it in GitHub Desktop.

Select an option

Save scruffydan/41ba5881fbc0bdc9d1c1823c087c70f7 to your computer and use it in GitHub Desktop.
#!/usr/bin/env bash
#==============================================================================
# A script to add lines of text to a file if they do not already exist.
# It creates a timestamped backup of the original file before making changes.
#
# Exits with status 1 if the target file does not exist, is not writable,
# or if an error occurs during writing.
# Exits with status 0 on successful completion (lines added or already exist).
#==============================================================================
# --- Configuration ---
# The file you want to modify. This can be a full path, e.g., "/etc/hosts"
TARGET_FILE="/path/to/file"
# Define the lines you want to ensure are in the file.
# Using a Bash array is a clean and safe way to handle lines with spaces
# or special characters.
LINES_TO_ADD=(
'line to add'
'line 2 to add'
'line 3 to add'
'etc'
)
# --- Script Logic ---
echo "Starting script. Processing file: $TARGET_FILE"
echo "================================================="
# 1. Pre-flight checks
# Check if the file exists. If not, exit with an error.
if [ ! -f "$TARGET_FILE" ]; then
# Send error messages to stderr
echo "ERROR: Target file '$TARGET_FILE' does not exist." >&2
exit 1
fi
# Check if the file is writable. If not, exit with an error.
if [ ! -w "$TARGET_FILE" ]; then
echo "ERROR: Target file '$TARGET_FILE' is not writable. Try running with sudo." >&2
exit 1
fi
# 2. Create a timestamped backup. This runs only if the pre-flight checks passed.
TIMESTAMP=$(date +'%Y-%m-%d_%H-%M-%S')
BACKUP_FILE="${TARGET_FILE}.backup_${TIMESTAMP}"
echo "-> File exists and is writable. Creating backup at: $BACKUP_FILE"
cp "$TARGET_FILE" "$BACKUP_FILE"
if [ $? -ne 0 ]; then
echo "ERROR: Failed to create backup file." >&2
exit 1
fi
echo # Adding a newline for better readability
# 3. Iterate over each line and add it if it doesn't exist.
# A flag is used to ensure a newline is only added before the *first*
# new line is written to the file.
first_addition=true
for line in "${LINES_TO_ADD[@]}"; do
# Check if the line already exists in the target file.
# -q : quiet mode, don't output anything.
# -F : treat the string as a fixed string, not a regular expression.
# -x : match the entire line exactly.
if grep -qFx -- "$line" "$TARGET_FILE"; then
echo "EXISTS: $line"
else
echo "ADDING: $line"
# Check if this is the first line we're adding in this run.
if [ "$first_addition" = true ]; then
# Add a newline BEFORE the first added line.
echo -e "\n$line" >> "$TARGET_FILE"
# Set the flag to false so subsequent lines won't get a preceding newline.
first_addition=false
else
# For all other lines, add them without a preceding newline.
echo "$line" >> "$TARGET_FILE"
fi
# Check for write errors after attempting to append.
if [ $? -ne 0 ]; then
echo "ERROR: Failed to write to '$TARGET_FILE'." >&2
# The file is now partially modified; the backup is crucial for recovery.
exit 1
fi
fi
done
echo "================================================="
echo "Script finished successfully."
# 4. Exit with success code 0.
exit 0
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment