Improvement of the Smart Menu Bar Management script
I’ve made a few updates to my Bartender triggers that allow me to switch configurations depending on whether the screen has a notch or not.
Only one script is now required.
#!/bin/zsh
# ==============================================================================
# Script: detect_main_display.sh
#
# Purpose:
# Detects whether the MAIN display (the one with the menu bar) is an
# EXTERNAL monitor or the INTERNAL MacBook screen.
#
# Output:
# - Prints "true" and exits 0 if the main display is EXTERNAL (no notch)
# - Prints "false" and exits 1 if the main display is INTERNAL (has a notch)
#
# Notes:
# - Works whether the MacBook lid is open or closed (clamshell mode).
# - When the lid is closed, macOS doesn't even list the internal screen,
# so the internal block simply won't exist in the output.
# - LANG=en_US.UTF-8 forces system_profiler to output in English,
# regardless of the system's configured language, so the string
# matching below stays reliable.
# ==============================================================================
# Step 1: Get the full display info from macOS, forced to English output.
DISPLAY_INFO=$(LANG=en_US.UTF-8 system_profiler SPDisplaysDataType 2>/dev/null)
# Step 2: Default assumption is "main display is NOT internal"
# (this will be flipped to "true" only if proven otherwise below).
MAIN_IS_INTERNAL="false"
# Step 3: Split the system_profiler output into one "block" per display.
#
# Each display starts with a line indented by exactly 8 spaces followed by
# a name and a colon, e.g.:
# " S34C65xT:"
# " Color LCD:"
#
# We can't split on blank lines (system_profiler doesn't always insert one
# between displays), so instead we use awk to start a new block every time
# we see a line matching that exact indentation pattern.
#
# Each finished block is emitted with a NUL byte (\0) separator instead of
# a newline, because display names/properties could theoretically contain
# newline-unsafe characters — NUL is the safest delimiter for `read -d ''`.
while IFS= read -r -d '' BLOCK; do
# Step 4: For each display block, check if it is BOTH:
# - the main display ("Main Display: Yes")
# - AND an internal display ("Connection Type: Internal")
# These two lines only appear together in the SAME block for the
# internal MacBook screen when it is currently the main display.
if [[ "$BLOCK" == *"Main Display: Yes"* ]] && [[ "$BLOCK" == *"Connection Type: Internal"* ]]; then
MAIN_IS_INTERNAL="true"
fi
done < <(awk '
# Detect the start of a new display block: exactly 8 spaces of
# indentation, then a non-space character, ending with a colon.
/^ [^ ].*:$/ {
# If we already accumulated a previous block, flush it out
# (separated by a NUL byte) before starting the new one.
if (block != "") printf "%s\0", block
block = ""
}
# Accumulate every line (including the header line) into the
# current block.
{ block = block $0 "\n" }
# Flush the very last block once the input ends.
END { if (block != "") printf "%s\0", block }
' <<< "$DISPLAY_INFO")
# Step 5: Output the final result based on what we found.
if [[ "$MAIN_IS_INTERNAL" == "true" ]]; then
# Main display is the internal MacBook screen (has a notch)
echo "false"
exit 1
else
# Main display is an external monitor (no notch)
echo "true"
exit 0
fi