This bash script provides functionality to check and sync environment files in your project.
Features
Checks .env files against a template (.env.template)
Identifies missing variables in .env files
Offers to sync .env files with the template
Skips syncing content for specified files
Usage
Source code in my Github repository here:
Check file here: misc/check_env_files.sh at main ยท khuepm/misc
Place the script (check_env_files.sh) in your project root directory.
Ensure you have a .env.template file with all required environment variables.
-
Make the script executable:
chmod +x checkenv.sh
- Run the script:
./checkenv.sh
- (optional) Add to
package.json
to check every start yarn
{
โฆ
scripts: {
"prestart": "sh checkenv.sh",
}
}
What it does
- Checking Environment Files:
The script checks all .env* files in the current directory against .env.template.
It displays missing variables in each file.
A summary of errors (if any) is shown for each file.
2. Syncing Environment Files:
If errors are found, the script offers to sync .env files with .env.template.
If you choose to sync (by entering โyโ), the script will:
Comment out variables not present in the template
Add new variables from the template
keep existing variables: preserving the current value and adding a comment with the template value
Configuration
- The script uses .env.template as the reference. Ensure this file contains all required variables for your project.
Note
After syncing, the script cleans the yarn cache. You may want to adjust or remove this step based on your project needs.
- Comment out yarn cache clean
How do I created it?
1. Initial Setup:
#!/bin/bash
template=".env.template"
# Check if the template file exists
if [ ! -f "$template" ]; then
echo "Error: $template not found"
return 1
fi
This section sets up the script and defines the template file. It also checks if the template file exists.
2. check_env_files() function:
# Use for later step, a flag to notice when we need to sync the .env
errors_found=false
check_env_files() {
files_not_to_check=(".env.template")
# Get all .env files in the current directory
files_to_check=($(find . -maxdepth 1 -type f -name '.env*'))
# Remove files that are in files_not_to_check
for file in "${files_not_to_check[@]}"; do
files_to_check=(${files_to_check[@]/$file})
done
# Remove any empty elements
files_to_check=(${files_to_check[@]})
# Get terminal height and width
terminal_height=$(tput lines)
terminal_width=$(tput cols)
# Variables to store output and result
output=""
result=""
# Function to update the screen, keep to notice text at the bottom of screen
update_screen() {
# Clear the screen
tput clear
# Print the output
echo "$output"
# Move cursor to the bottom and print the result
tput cup $((terminal_height - 3)) 0
printf '%*s\n' "$terminal_width" '' | tr ' ' '-'
echo "$result"
printf '%*s\n' "$terminal_width" '' | tr ' ' '-'
# Move cursor back to the top
tput cup 0 0
}
for file in "${files_to_check[@]}"; do
if [ -f "$file" ]; then
output+="\n"
output+="Checking $file...\n\n"
error_count=0
while IFS= read -r line || [[ -n "$line" ]]; do
key=$(echo "$line" | cut -d'=' -f1)
if ! grep -q "^$key=" "$file"; then
output+="\033[31m ๐ Missing in $file: $key\033[0m\n"
((error_count++))
errors_found=true
fi
update_screen
done < "$template"
# Update final result
output+="\n\n==========================================\n"
if [ $error_count -gt 0 ]; then
result+="\n\033[31mโ Done checking $file with $error_count error(s)\033[0m\n"
output+="$result"
else
result+="\n\033[32mโ
Done checking $file with no errors\033[0m\n"
output+="$result"
fi
update_screen
output+="\n"
# Add a small delay to make the result visible at first check
# Remove if you want to see the result immediately
if [ "$file" = "${files_to_check[0]}" ]; then
sleep 1
fi
else
#output+="\033[33m๐ Check $file: $file not found, skipping\033[0m\n"
#result+="\033[33mโ ๏ธ $file not found, skipping\033[0m\n"
update_screen
fi
done
# Clear the result at the end
result=""
update_screen
# Reset terminal settings
tput rmcup # Exit alternate screen buffer
tput cnorm # Show cursor
tput sgr0 # Reset all attributes
# Clear the screen and move cursor to top-left
clear
tput cup 0 0
# Display final output
echo "$output"
}
This function is responsible for checking .env files against the template. It does the following:
Finds all .env files in the current directory
Removes files that should not be checked
Sets up a dynamic terminal display
Checks each .env file against the template, highlighting missing keys
Updates the screen with progress and results
The problem when template has an empty line or a comment line, the checker will not work property. So I need to adjust it a little bit:
...
while IFS= read -r line || [[ -n "$line" ]]; do
# Skip empty lines and comment lines
if [[ -z "$line" || "$line" =~ ^[[:space:]]*# ]]; then
continue
fi
...
3. sync_env_files() function:
This function synchronizes .env files with the template. It:
Finds all .env files to sync
For each file:
Comments out lines not in the template
Updates existing keys with new values from the template
-
Adds new keys from the template
sync_env_files() {
# Get all .env files in the current directory
files_to_sync=($(find . -maxdepth 1 -type f -name '.env*'))# Exclude .env.template from files to sync
files_to_sync=(${files_to_sync[@]/$template})# Remove any empty elements
files_to_sync=(${files_to_sync[@]})# Sync files
for file in "${files_to_sync[@]}"; do
if [ -f "$file" ]; then# Check if the file is in the list of files not to sync echo "Syncing $file with $template..." # Comment lines not in template while IFS= read -r line || [[ -n "$line" ]]; do if [[ $line =~ ^[[:space:]]*# || -z $line ]]; then continue # Skip comments and empty lines fi key=$(echo "$line" | cut -d'=' -f1) if ! grep -q "^$key=" "$template"; then sed -i '' "s|^$key=.*|# $line # Not in template|" "$file" echo "\033[31m Commented: $key (not in template)\033[0m" fi done < "$file" while IFS= read -r line || [[ -n "$line" ]]; do if [[ $line =~ ^[[:space:]]*# || -z $line ]]; then continue # Skip comments and empty lines fi key=$(echo "$line" | cut -d'=' -f1) value=$(echo "$line" | cut -d'=' -f2-) if grep -q "^$key=" "$file"; then # Key exists, check if value is different current_value=$(grep "^$key=" "$file" | cut -d'=' -f2-) if [ "$current_value" != "$value" ]; then # Value is different, update it sed -i '' "/# $key=.*# Updated from template/d" "$file" sed -i '' "s|^$key=.*|# $key=$value # Updated from template\n$key=$current_value|" "$file" echo "\033[33m Updated: $key\033[0m" else echo " Skipped: $key (value unchanged)" fi else # Key doesn't exist, add it echo "$key=$value # Added from template" >> "$file" echo "\033[32m Added: $key\033[0m" fi done < "$template" echo "Finished syncing $file" echo fi
done
}
4. Main execution flow:
# Call the function
check_env_files
if [ "$errors_found" = true ]; then
# Ask user if they want to sync files
# If yes, call sync_env_files()
# After sync successfully, do clean the cache
# If no, cancel the operation
else
echo "No errors found in .env files. Sync not needed."
fi
This section calls the check_env_files() function and then, based on whether errors were found, either prompts the user to sync the files or informs them that no sync is needed.
Key features of this script:
Dynamic terminal display for real-time progress updates
Color-coded output for easy reading (red for errors, green for success, yellow for warnings)
Careful handling of existing values in .env files during sync
Option to sync files only if errors are found
This script is useful for maintaining consistency across multiple .env files in a project, ensuring that all required environment variables are present and up-to-date.
Top comments (0)