Automate Your Dev Workflow With Bash Scripts: A Simple Guide
Let’s be honest: we all waste time doing repetitive tasks. git add, git commit, npm install, docker build — rinse, repeat. If you’re typing the same commands every day, you’re not just wasting time — you’re inviting human error. Bash scripts aren’t magic, but they’re close. They’re lightweight, portable, and run everywhere. Let’s cut the fluff and automate the boring stuff.
1. Start Small: Automate Git Workflows
You probably run the same Git commands every time you commit. Why not wrap them?
Here’s a simple commit.sh script:
#!/bin/bash
# Simple commit script
echo "Staging all changes..."
git add .
echo "Enter commit message:"
read message
if [ -z "$message" ]; then
echo "Commit message is required!"
exit 1
fi
git commit -m "$message"
echo "Pushing to origin..."
git push origin $(git branch --show-current)
Make it executable:
chmod +x commit.sh
Now run:
./commit.sh
You can expand this: check for dirty repos, run tests before pushing, or enforce conventional commits. Start small, then iterate.
2. Project Setup in Seconds
Starting a new project? You always do the same setup: create directories, init Git, add a README, maybe a .gitignore.
Automate it:
#!/bin/bash
# setup-project.sh
echo "Enter project name:"
read name
mkdir "$name" && cd "$name" || exit
# Scaffold basic structure
mkdir src tests docs
# Init Git
git init
# Create basic files
echo "# $name" > README.md
touch .gitignore
echo "node_modules/" >> .gitignore
# Optional: init package.json
if command -v npm &> /dev/null; then
npm init -y > /dev/null
fi
echo "✅ Project '$name' set up!"
Now you go from zero to project skeleton in 10 seconds. No more copy-pasting folder structures.
3. Run Tests + Lint in One Command
You run npm test and npm run lint together, right? So why run them separately?
#!/bin/bash
# test-and-lint.sh
echo "Running linter..."
npm run lint
if [ $? -ne 0 ]; then
echo "❌ Lint failed. Fix issues before continuing."
exit 1
fi
echo "Running tests..."
npm test
if [ $? -ne 0 ]; then
echo "❌ Tests failed."
exit 1
fi
echo "✅ All checks passed."
Now one command tells you if your code is clean and working. Bonus: hook this into your pre-commit later.
4. Use Functions and Variables Like a Pro
Bash isn’t just for linear scripts. Use functions to organize logic.
#!/bin/bash
# utils.sh
BACKUP_DIR="/backups"
backup_file() {
local file=$1
if [ -f "$file" ]; then
cp "$file" "$BACKUP_DIR/$(basename "$file").$(date +%s).bak"
echo "Backed up $file"
else
echo "File $file not found."
fi
}
deploy() {
echo "Building..."
npm run build
echo "Deploying to server..."
scp -r dist/* user@server:/var/www/html
}
# Call functions based on args
case "$1" in
"backup")
backup_file "$2"
;;
"deploy")
deploy
;;
*)
echo "Usage: $0 {backup|deploy}"
;;
esac
Now you have a multi-purpose script:
./utils.sh backup app.js
./utils.sh deploy
5. Accept Arguments and Make It Flexible
Hardcoding paths or values kills reusability. Use arguments.
#!/bin/bash
# serve.sh - lightweight dev server
PORT=${1:-8080} # default to 8080
DIR=${2:-.}
echo "Serving $DIR on port $PORT"
python3 -m http.server $PORT --directory $DIR
Now:
./serve.sh # uses 8080 and current dir
./serve.sh 3000 # custom port
./serve.sh 3000 ./public # custom port + dir
Use getopts for more complex flags, but don’t overcomplicate early on.
6. Handle Errors and Exit Codes
A script that fails silently is worse than no script.
Always check exit codes:
npm install
if [ $? -ne 0 ]; then
echo "npm install failed"
exit 1
fi
Or use shorthand:
npm install || { echo "Install failed"; exit 1; }
And set set -e at the top to exit on any error:
#!/bin/bash
set -e # Exit immediately if a command fails
npm install
npm run build
npm publish
Now you won’t publish a broken build because npm install failed silently.
7. Where to Store Your Scripts
Don’t scatter scripts across projects. Pick a pattern:
-
Per-project: Keep
scripts/in your repo. Great for team-shared automation.
☕ Appreciative
Top comments (0)