Skip to content

Instantly share code, notes, and snippets.

@xdhmoore
Created September 9, 2020 13:32
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save xdhmoore/cb8321bbd00f2fe07e418d9fa93367ca to your computer and use it in GitHub Desktop.
Save xdhmoore/cb8321bbd00f2fe07e418d9fa93367ca to your computer and use it in GitHub Desktop.
Bash script to swap monitor configurations
#!/usr/bin/env bash
# Sometimes mac os assigns different ids to external monitors. The ids can swap back and forth (based on
# the order in which they are attached?). When the ids of two displays are switched, it's impossible
# (as far as I know) to determine which external monitor id goes with which physical device. Instead,
# this script just assumes the ids are backwards and switches the configuration for them.
# After all, you are calling the scripit, so something must be wrong...
#
# Note that this script depends heavily on the text output of displayplacer, so it may be somewhat brittle...
built_in_id=$(displayplacer list | grep -iB2 ' *Type *:.*built *in' | grep -i '^Persistent *screen *id' | sed -E 's/^[^:]*: *//g')
# Everything that is not a built-in is an external display
ext_ids=$(displayplacer list | grep -i '^Persistent *screen *id' | grep -v "$built_in_id" | sed -E 's/^[^:]*: *//g')
# Assuming two external displays:
first_ext_id=$(echo "$ext_ids" | sort | head -n1)
second_ext_id=$(echo "$ext_ids" | sort -r | head -n1)
# Get the current display config, swap the external display ids, and rerun it
my_config="$(displayplacer list | grep -E '^ *displayplacer *')"
toggle_config=$(echo "$my_config" | sed "s/${first_ext_id}/frogdinosaurcat/g")
toggle_config=$(echo "$toggle_config" | sed "s/${second_ext_id}/${first_ext_id}/g")
toggle_config=$(echo "$toggle_config" | sed "s/frogdinosaurcat/${second_ext_id}/g")
eval $toggle_config
@kinghippos3
Copy link

Noobie here. Mainly just trying to solve the MAC screen arrangement problem. I got displayplacer to work... however, the ID's keep swapping between my monitors. How do I use your script to just flip the monitors? I tried copying and pasting your code into a "run shell script" application/workflow... however nothing seems to happen. Thanks in advance...

@xdhmoore
Copy link
Author

I don't have that work Mac anymore but I think I created a file with extension sh and then searched and invoked it via spotlight. But for starters you probably will want to try running the file from the command line.

@xdhmoore
Copy link
Author

To debug you might try adding echo statements to see what the variable values are being set to. Maybe your monitor configuration is different than mine. I had a laptop screen and two identical external screens, but there also may be different versions of that scenario I hadn't considered.

@FloWi
Copy link

FloWi commented Nov 28, 2021

@xdhmoore Thanks a lot for that script! Made my day!

@rafaelmaeuer
Copy link

Thanks a lot for providing the script. I needed to fix recognition of internal monitor (-iB3) and handle case when lid is closed. Here my updated script if anyone else needs this:

#!/usr/bin/env bash

# Sometimes mac os assigns different ids to external monitors. The ids can swap back and forth (based on 
# the order in which they are attached?). When the ids of two displays are switched, it's impossible
# (as far as I know) to determine which external monitor id goes with which physical device. Instead,
# this script just assumes the ids are backwards and switches the configuration for them.
# After all, you are calling the scripit, so something must be wrong...
#
# Note that this script depends heavily on the text output of displayplacer, so it may be somewhat brittle...

built_in_id=$(displayplacer list | grep -iB3 ' *Type *:.*built *in' | grep -i '^Persistent *screen *id' | sed -E 's/^[^:]*: *//g')

# Everything that is not a built-in is an external display
if [[ -n "$built_in_id" ]]; then
  ext_ids=$(displayplacer list | grep -i '^Persistent *screen *id' | grep -v "$built_in_id" | sed -E 's/^[^:]*: *//g')
else
  ext_ids=$(displayplacer list | grep -i '^Persistent *screen *id' | sed -E 's/^[^:]*: *//g')
fi

# Assuming two external displays:
first_ext_id=$(echo "$ext_ids" | sort | head -n1)
second_ext_id=$(echo "$ext_ids" | sort -r | head -n1)

# Get the current display config, swap the external display ids, and rerun it
my_config="$(displayplacer list | grep -E '^ *displayplacer *')"
toggle_config=$(echo "$my_config" | sed "s/${first_ext_id}/frogdinosaurcat/g")
toggle_config=$(echo "$toggle_config" | sed "s/${second_ext_id}/${first_ext_id}/g")
toggle_config=$(echo "$toggle_config" | sed "s/frogdinosaurcat/${second_ext_id}/g")
eval $toggle_config

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment