Skip to content

Instantly share code, notes, and snippets.

@timokoola
Created March 26, 2025 06:59
Show Gist options
  • Select an option

  • Save timokoola/2a7c3006df05bc9718b78326f6237b50 to your computer and use it in GitHub Desktop.

Select an option

Save timokoola/2a7c3006df05bc9718b78326f6237b50 to your computer and use it in GitHub Desktop.
#!/bin/bash
#
# Chrome Profile Lister
# Lists all Google Chrome profiles with email addresses only
# Format designed for easy selection and extraction in Keyboard Maestro
#
# Process command-line options
SHOW_HEADER=true
FORMAT="default"
while [[ $# -gt 0 ]]; do
case $1 in
--no-header)
SHOW_HEADER=false
shift
;;
--format)
FORMAT="$2"
shift 2
;;
*)
echo "Unknown option: $1"
echo "Usage: $0 [--no-header] [--format km|default]"
exit 1
;;
esac
done
# Set the Chrome profile directory path
CHROME_DIR="$HOME/Library/Application Support/Google/Chrome"
# Check if Chrome directory exists
if [ ! -d "$CHROME_DIR" ]; then
echo "Chrome directory not found: $CHROME_DIR"
exit 1
fi
# Function to extract email from a preferences file
extract_email() {
local pref_file="$1"
# Check if the file exists
if [ ! -f "$pref_file" ]; then
echo ""
return
fi
# Extract email using grep and sed
# Look for email in the preferences file
local email=$(grep -o '"email":"[^"]*"' "$pref_file" | head -1 | sed 's/"email":"//;s/"$//')
# If email not found, check for account info
if [ -z "$email" ]; then
email=$(grep -o '"last_used_user_account":"[^"]*"' "$pref_file" | head -1 | sed 's/"last_used_user_account":"//;s/"$//')
fi
echo "$email"
}
# Function to extract profile name
extract_profile_name() {
local pref_file="$1"
local profile_dir="$2"
# Default name based on directory
local default_name=$(basename "$profile_dir")
# Check if the file exists
if [ ! -f "$pref_file" ]; then
echo "$default_name"
return
fi
# Extract profile name using grep and sed
local name=$(grep -o '"name":"[^"]*"' "$pref_file" | head -1 | sed 's/"name":"//;s/"$//')
# If no name found, use directory name
if [ -z "$name" ]; then
echo "$default_name"
else
echo "$name"
fi
}
# Function to extract domain from email
extract_domain() {
local email="$1"
if [[ "$email" == *"@"* ]]; then
echo "${email#*@}"
else
echo "zzznotsignedin"
fi
}
# Function to extract local part from email
extract_local_part() {
local email="$1"
if [[ "$email" == *"@"* ]]; then
echo "${email%%@*}"
else
echo "$email"
fi
}
# Temporary file for profile data
TEMP_FILE=$(mktemp)
# Function to collect profile information
collect_profile_info() {
local profile_dir="$1"
local profile_name=$(extract_profile_name "$profile_dir/Preferences" "$profile_dir")
local email=$(extract_email "$profile_dir/Preferences")
# Skip if no email (not signed in)
if [ -z "$email" ]; then
return
fi
if [ "$FORMAT" = "km" ]; then
# Store domain, local part, and profile info for sorting
domain=$(extract_domain "$email")
local_part=$(extract_local_part "$email")
# Store full profile information for KM format
# Format: "Display Name|email_address"
echo "$domain|$local_part|$profile_name ($domain)|$email" >> "$TEMP_FILE"
else
# Default format - just print
printf "%-20s %-35s %s\n" "$profile_name" "$email" "$profile_dir"
fi
}
# Print header if requested for default format
if [ "$SHOW_HEADER" = true ] && [ "$FORMAT" = "default" ]; then
echo "===== Chrome Profiles with Email ====="
printf "%-20s %-35s %s\n" "Profile Name" "Email Address" "Profile Directory"
echo "------------------------------------------------------------------------------------"
fi
# Process Default profile
if [ -d "$CHROME_DIR/Default" ]; then
if [ "$FORMAT" = "default" ]; then
profile_name=$(extract_profile_name "$CHROME_DIR/Default/Preferences" "$CHROME_DIR/Default")
email=$(extract_email "$CHROME_DIR/Default/Preferences")
if [ -n "$email" ]; then
printf "%-20s %-35s %s\n" "$profile_name" "$email" "$CHROME_DIR/Default"
fi
else
collect_profile_info "$CHROME_DIR/Default"
fi
fi
# Process numbered profiles
find "$CHROME_DIR" -maxdepth 1 -type d -name "Profile*" | sort | while read -r profile_dir; do
# Skip if directory doesn't exist
if [ ! -d "$profile_dir" ]; then
continue
fi
if [ "$FORMAT" = "default" ]; then
profile_name=$(extract_profile_name "$profile_dir/Preferences" "$profile_dir")
email=$(extract_email "$profile_dir/Preferences")
if [ -n "$email" ]; then
printf "%-20s %-35s %s\n" "$profile_name" "$email" "$profile_dir"
fi
else
collect_profile_info "$profile_dir"
fi
done
# For KM format, output the sorted list with display names and emails separated by |
if [ "$FORMAT" = "km" ]; then
# Sort the data by domain and then by local part
sort "$TEMP_FILE" -o "$TEMP_FILE"
# Output the sorted data in a format Keyboard Maestro can easily parse
while IFS="|" read -r domain local_part display_name email; do
echo "$display_name|$email"
done < "$TEMP_FILE"
fi
# Clean up
rm -f "$TEMP_FILE"
#!/bin/bash
#
# Chrome Profile Opener
# Opens a new Chrome window with the specified profile (by email address or directory name)
#
# Process command line options
USE_DIRECTORY=false
EMAIL=""
DIRECTORY=""
# Parse arguments
while [[ $# -gt 0 ]]; do
case $1 in
--directory)
USE_DIRECTORY=true
DIRECTORY="$2"
shift 2
;;
*)
EMAIL="$1"
shift
;;
esac
done
# Check if either email or directory was provided
if [ "$USE_DIRECTORY" = false ] && [ -z "$EMAIL" ]; then
echo "Usage: $0 <email_address> OR $0 --directory <directory_name>"
exit 1
fi
if [ "$USE_DIRECTORY" = true ] && [ -z "$DIRECTORY" ]; then
echo "Error: No directory specified with --directory flag"
exit 1
fi
CHROME_DIR="$HOME/Library/Application Support/Google/Chrome"
CHROME_APP="/Applications/Google Chrome.app/Contents/MacOS/Google Chrome"
# Alternative Chrome locations to check if the default isn't found
ALT_CHROME_LOCATIONS=(
"/Applications/Google Chrome.app/Contents/MacOS/Google Chrome"
"/Applications/Google Chrome Beta.app/Contents/MacOS/Google Chrome Beta"
"/Applications/Google Chrome Dev.app/Contents/MacOS/Google Chrome Dev"
"/Applications/Google Chrome Canary.app/Contents/MacOS/Google Chrome Canary"
)
# Find Chrome executable
for chrome_path in "${ALT_CHROME_LOCATIONS[@]}"; do
if [ -f "$chrome_path" ]; then
CHROME_APP="$chrome_path"
break
fi
done
# Check if Chrome executable exists
if [ ! -f "$CHROME_APP" ]; then
echo "Error: Google Chrome application not found"
exit 1
fi
# Function to find profile directory by email
find_profile_by_email() {
local email="$1"
local profile_dir=""
# Check Default profile first
if [ -f "$CHROME_DIR/Default/Preferences" ]; then
local default_email=$(grep -o '"email":"[^"]*"' "$CHROME_DIR/Default/Preferences" | head -1 | sed 's/"email":"//;s/"$//')
if [ -z "$default_email" ]; then
default_email=$(grep -o '"last_used_user_account":"[^"]*"' "$CHROME_DIR/Default/Preferences" | head -1 | sed 's/"last_used_user_account":"//;s/"$//')
fi
if [ "$default_email" = "$email" ]; then
echo "Default"
return 0
fi
fi
# Check numbered profiles
find "$CHROME_DIR" -maxdepth 1 -type d -name "Profile*" | while read -r dir; do
if [ -f "$dir/Preferences" ]; then
local profile_email=$(grep -o '"email":"[^"]*"' "$dir/Preferences" | head -1 | sed 's/"email":"//;s/"$//')
if [ -z "$profile_email" ]; then
profile_email=$(grep -o '"last_used_user_account":"[^"]*"' "$dir/Preferences" | head -1 | sed 's/"last_used_user_account":"//;s/"$//')
fi
if [ "$profile_email" = "$email" ]; then
# Extract profile name from directory path
echo "$(basename "$dir")"
return 0
fi
fi
done
# If no matching profile found
echo ""
return 1
}
# Main execution path
if [ "$USE_DIRECTORY" = true ]; then
# Using directory directly
if [ "$DIRECTORY" = "Default" ]; then
PROFILE="Default"
else
PROFILE="$DIRECTORY"
fi
echo "Opening Chrome with profile directory: $PROFILE"
else
# Using email to find profile
PROFILE=$(find_profile_by_email "$EMAIL")
if [ -z "$PROFILE" ]; then
echo "Error: No Chrome profile found for email: $EMAIL"
exit 1
fi
echo "Opening Chrome with profile: $PROFILE ($EMAIL)"
fi
# Open Chrome with the specified profile
"$CHROME_APP" --profile-directory="$PROFILE" --new-window &
# Wait a moment to ensure Chrome launches before script exits
sleep 1
exit 0
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment