macOS automatically creates .DS_Store files in every folder you open in Finder. They're harmless on your own machine but are notorious for cluttering Git repositories. This guide covers how to delete them, keep them out of Git, and prevent future pollution.
What Is a .DS_Store File?
DS_Store stands for Desktop Services Store. macOS creates this hidden file in each directory to store metadata about the folder's Finder view: icon positions, window size, background image, sort order, and other display preferences.
The file is invisible in Finder by default (it starts with a dot), but it shows up in Git diffs and git status output, where it creates noise and accidental commits.
Delete All .DS_Store Files in the Current Folder
Run this command from your project's root directory to recursively find and delete every .DS_Store file:
find . -name ".DS_Store" -delete
The find command searches from the current directory (.) through all subdirectories. -name ".DS_Store" matches the filename exactly, and -delete removes each match.
To see what would be deleted before actually deleting (a dry run):
find . -name ".DS_Store"
This lists all matching files without removing them. Once you're confident, add -delete to do the cleanup.
Delete .DS_Store Files from a Specific Directory
# Delete from a specific path
find /Users/yourname/projects/myapp -name ".DS_Store" -delete
# Delete from your entire home directory
find ~ -name ".DS_Store" -delete
Remove .DS_Store Files Already Committed to Git
If .DS_Store files were committed before you added them to .gitignore, deleting them from disk isn't enough — they remain in Git's history and will keep reappearing. You need to untrack them:
# Remove from Git's index (stops tracking), but keep the file on disk
git rm --cached .DS_Store
# Remove all .DS_Store files from tracking recursively
git rm --cached -r --ignore-unmatch "**/.DS_Store"
# Then commit the removal
git commit -m "Remove .DS_Store files from tracking"
Note:--cachedremoves the file from Git's index without deleting it from your filesystem. Without--cached, Git would delete the file from disk too.
Prevent .DS_Store from Being Committed — .gitignore
Add .DS_Store to your project's .gitignore to prevent it from ever being committed:
# .gitignore
.DS_Store
**/.DS_Store
The **/.DS_Store pattern matches .DS_Store in any subdirectory, not just the root. Commit the .gitignore change so your whole team benefits.
Global .gitignore — Apply to All Your Repositories
If you work on many projects, set a global .gitignore so you never have to think about this again:
# Create (or edit) the global gitignore file
echo ".DS_Store" >> ~/.gitignore_global
# Tell Git to use it for all repositories
git config --global core.excludesfile ~/.gitignore_global
This applies to every repository on your machine, without touching each project's own .gitignore.
Other macOS Clutter Files Worth Ignoring
While you're at it, these other macOS artifacts are also worth adding to your .gitignore:
# macOS metadata and system files
.DS_Store
**/.DS_Store
.AppleDouble
.LSOverride
._*
# macOS Spotlight index files
.Spotlight-V100
.Trashes
# macOS icon files
Icon?
Why .DS_Store Files Matter in Git
Leaving .DS_Store files unignored causes several practical problems:
- Polluted
git status— they appear as untracked files constantly - Accidental commits — developers commit them without realizing
- Merge conflicts — two developers editing Finder view preferences in the same folder creates a merge conflict on a file with no meaningful content
- Repository bloat — they accumulate over time if not cleaned up
- Security consideration —
.DS_Storefiles can leak folder structure information about your machine
Summary
Run find . -name ".DS_Store" -delete to clean up existing files. Add .DS_Store to .gitignore (or a global ~/.gitignore_global) to prevent future commits. If the files were already committed, use git rm --cached to untrack them without deleting them from disk.
Apache Maven is the most widely used Java build tool. macOS does not ship Maven pre-installed, so you need to add it yourself — either manually from the official download or through Homebrew. This guide covers both approaches, plus how to set up your shell environment so the mvn command is available in every terminal session.
Prerequisites
Maven requires a JDK. Verify Java is installed before proceeding:
java -version
# java version "21.0.2" 2024-01-16 LTS
If this fails, install a JDK first (e.g., from Adoptium or via brew install openjdk). Maven 3.9+ requires Java 8 or later; Maven 4.x requires Java 17 or later.
Option 1: Manual Installation (Recommended for Version Control)
Step 1 — Download the Binary Archive
Go to the Apache Maven download page and grab the binary tar.gz for the latest stable release (3.9.x as of this writing). You can also download it directly from the terminal:
# Replace 3.9.6 with the current version from maven.apache.org/download
curl -O https://dlcdn.apache.org/maven/maven-3/3.9.6/binaries/apache-maven-3.9.6-bin.tar.gz
Step 2 — Extract to a Stable Location
Extract the archive to a directory you control. A dedicated runtime directory in your home folder keeps things tidy:
mkdir -p ~/DevRuntime
tar -xzf apache-maven-3.9.6-bin.tar.gz -C ~/DevRuntime
ls ~/DevRuntime/apache-maven-3.9.6/
# bin boot conf lib LICENSE NOTICE README.txt
Step 3 — Set MAVEN_HOME and Update PATH
macOS Catalina and later use Zsh as the default shell. Add environment variables to ~/.zshenv — this file is sourced for all shell sessions, including non-interactive ones started by IDEs and build pipelines:
# Open ~/.zshenv in any text editor, or append with echo:
echo 'export MAVEN_HOME="$HOME/DevRuntime/apache-maven-3.9.6"' >> ~/.zshenv
echo 'export PATH="$MAVEN_HOME/bin:$PATH"' >> ~/.zshenv
After editing, reload the file in your current shell:
source ~/.zshenv
Step 4 — Verify
mvn --version
# Apache Maven 3.9.6 (bc0240f3c744dd6b6ec2920b3cd08dcc295161ae)
# Maven home: /Users/yourname/DevRuntime/apache-maven-3.9.6
# Java version: 21.0.2, vendor: Eclipse Adoptium, runtime: /Library/Java/...
# Default locale: en_US, platform encoding: UTF-8
# OS name: "mac os x", version: "14.2", arch: "aarch64", family: "mac"
The output confirms Maven is on the PATH and shows which JDK it's using.
Option 2: Install via Homebrew
Homebrew is the simpler option if you don't need to manage multiple Maven versions:
brew install maven
Homebrew installs Maven to /opt/homebrew/opt/maven (Apple Silicon) or /usr/local/opt/maven (Intel) and adds it to your PATH automatically. Verify:
mvn --version
# Apache Maven 3.9.6
which mvn
# /opt/homebrew/bin/mvn
To upgrade later: brew upgrade maven. To see available versions: brew info maven.
Switching Between Multiple Maven Versions
If you need different Maven versions for different projects (e.g., Maven 3.6 for a legacy project, Maven 3.9 for a new one), the manual approach makes switching straightforward. Extract each version to its own subdirectory:
~/DevRuntime/
apache-maven-3.6.3/
apache-maven-3.9.6/
Then update MAVEN_HOME in ~/.zshenv to point at the version you want active, and source ~/.zshenv. Alternatively, use a version manager like sdkman, which handles Java and Maven versions together:
# Install sdkman (if not already installed)
curl -s "https://get.sdkman.io" | bash
# Install a specific Maven version
sdk install maven 3.9.6
# Switch to a different version
sdk use maven 3.6.3
The ~/.zshenv vs ~/.zshrc Difference
| File | When sourced | Best for |
|---|---|---|
~/.zshenv | Every Zsh session — interactive, non-interactive, login, and script | Environment variables like MAVEN_HOME, JAVA_HOME, PATH |
~/.zshrc | Interactive shells only | Aliases, prompt configuration, completions |
~/.zprofile | Login shells only | Commands that should run once at login |
Using ~/.zshenv for MAVEN_HOME and PATH ensures your IDE (IntelliJ IDEA, VS Code) picks up the correct Maven even when it launches a non-interactive shell to run builds.
Running Your First Build
Once Maven is installed, create a simple project to confirm everything works end-to-end:
mvn archetype:generate \
-DgroupId=com.example \
-DartifactId=hello-maven \
-DarchetypeArtifactId=maven-archetype-quickstart \
-DarchetypeVersion=1.4 \
-DinteractiveMode=false
cd hello-maven
mvn package
java -cp target/hello-maven-1.0-SNAPSHOT.jar com.example.App
# Hello World!
Configuring the Local Repository
Maven downloads dependencies to ~/.m2/repository by default. To change this location (useful if your home directory is on a small SSD), edit ~/.m2/settings.xml:
<settings>
<localRepository>/Volumes/FastDrive/.m2/repository</localRepository>
</settings>
Summary
To install Maven on macOS manually: download the binary archive, extract it to a stable directory like ~/DevRuntime, set MAVEN_HOME and update PATH in ~/.zshenv, then run source ~/.zshenv and verify with mvn --version. For a simpler one-command install, use brew install maven. Use ~/.zshenv (not ~/.zshrc) for environment variables so that IDEs and non-interactive shells also see the correct Maven installation.
macOS ships with Bash, but the version Apple includes is ancient — Bash 3.2 from 2007. If your scripts rely on features introduced in Bash 4 or later (associative arrays, mapfile, globstar), you need to know what you're running and how to upgrade. Here are all the ways to check.
Method 1: bash --version
The most direct way — run the bash binary with the --version flag:
bash --version
On a stock macOS installation you'll see:
GNU bash, version 3.2.57(1)-release (arm64-apple-darwin23)
Copyright (C) 2007 Free Software Foundation, Inc.
License GPLv2+: GNU GPL version 2 or later <http://gnu.org/licenses/gpl.html>
If you've installed a newer version via Homebrew, the output will reflect that instead (e.g., 5.2.26(1)-release).
Method 2: $BASH_VERSION Variable
Inside any running Bash session, the $BASH_VERSION variable always holds the current shell's version:
echo $BASH_VERSION
# 3.2.57(1)-release (Apple's built-in)
# 5.2.26(1)-release (Homebrew-installed)
This is useful inside scripts when you want to check the runtime version programmatically:
#!/bin/bash
if [[ "${BASH_VERSINFO[0]}" -lt 4 ]]; then
echo "This script requires Bash 4 or later. You have: $BASH_VERSION" >&2
exit 1
fi
echo "Good — running Bash ${BASH_VERSINFO[0]}.${BASH_VERSINFO[1]}"
$BASH_VERSINFO is an array: [0] is the major version, [1] is the minor version.
Method 3: which bash and file Path Check
To see which bash binary is actually on your PATH:
which bash
# /bin/bash (Apple's system bash)
# /opt/homebrew/bin/bash (Homebrew bash on Apple Silicon)
# /usr/local/bin/bash (Homebrew bash on Intel)
If which bash shows /bin/bash but you installed Homebrew's bash, your PATH may not be putting /opt/homebrew/bin first. Check with echo $PATH.
Why Does macOS Ship Bash 3.2?
This comes down to licensing. Bash 3.2 is the last version released under GPLv2. Starting with Bash 4.0, the project moved to GPLv3. Apple's legal policy prevents them from shipping GPLv3 software in macOS, so they're stuck distributing the 2007 Bash 3.2 binary.
This is also why Apple switched the default interactive shell to Zsh in macOS Catalina (10.15, 2019). Zsh uses the MIT license — no GPL restrictions. If you open Terminal on a fresh Mac, you're already using Zsh, not Bash.
Bash 3.2 vs Bash 5: What's Missing
| Feature | Bash 3.2 | Bash 4+ |
|---|---|---|
Associative arrays (declare -A) | Not available | Bash 4.0+ |
mapfile / readarray | Not available | Bash 4.0+ |
** globstar (recursive glob) | Not available | Bash 4.0+ with shopt -s globstar |
read -i (default value in read) | Not available | Bash 4.0+ |
| Case-insensitive matching | Limited | Bash 4.0+ with shopt -s nocasematch |
| Improved string manipulation | Basic | Bash 4.0+ adds ${var^^}, ${var,,} |
Nameref variables (declare -n) | Not available | Bash 4.3+ |
Installing a Modern Bash with Homebrew
To get Bash 5 on macOS:
brew install bash
Homebrew installs it at /opt/homebrew/bin/bash (Apple Silicon) or /usr/local/bin/bash (Intel). Verify:
/opt/homebrew/bin/bash --version
# GNU bash, version 5.2.26(1)-release
Making Homebrew Bash the Default
To use it as your default login shell, first add it to the list of approved shells, then change your shell:
# Add to /etc/shells (requires sudo)
echo "/opt/homebrew/bin/bash" | sudo tee -a /etc/shells
# Change your login shell
chsh -s /opt/homebrew/bin/bash
Open a new terminal session and verify:
echo $BASH_VERSION
# 5.2.26(1)-release
Note: Even after this, /bin/bash still exists and is still Bash 3.2. Scripts with #!/bin/bash shebangs continue to use the old version. Use #!/usr/bin/env bash to pick up whichever bash is first on your PATH.
Should You Upgrade or Switch to Zsh?
Since macOS Catalina, Zsh is Apple's recommended default shell for interactive use. Zsh has feature parity with modern Bash and adds improvements like better tab completion, array handling, and the Oh My Zsh ecosystem. If you're writing shell scripts for portability across macOS and Linux, consider:
- Use Zsh (
#!/bin/zsh) for macOS-specific scripts - Use POSIX sh (
#!/bin/sh) for maximum portability - Use Bash 5 from Homebrew (
#!/usr/bin/env bash) for scripts that need Bash-specific Bash 4+ features on macOS
Summary
Check the Bash version on macOS with bash --version or by reading $BASH_VERSION inside a script. macOS ships Bash 3.2 (from 2007) because Apple cannot distribute newer Bash versions due to the GPLv3 license. Install Bash 5 via brew install bash for access to associative arrays, globstar, mapfile, and other modern features. macOS Catalina and later default to Zsh; use #!/usr/bin/env bash in scripts so they pick up whichever bash is first on the PATH.
Details of the cool announcements can be found here
https://developer.apple.com/wwdc19/
macOS's next big upgrade will be called Catalina and with it comes a big change for developers.
By default macOS has used bash as the default shell. New user accounts in macOS Catalina will use zsh. Zsh is an open source shell very popular and comes with a ton of features.
Zsh git repository link is https://github.com/robbyrussell/oh-my-zsh/
Apple support page contains details about how to set the Zsh shell as default for macOS Mojave and earlier https://support.apple.com/en-us/HT208050

