Created
March 26, 2025 06:59
-
-
Save timokoola/2a7c3006df05bc9718b78326f6237b50 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/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" |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/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