Skip to content

Instantly share code, notes, and snippets.

@mrpnelson
Last active May 16, 2021
Embed
What would you like to do?
Mac WiFi Preferred Network Refresh Script
#!/bin/bash
# ------------------------------------------------------------------------------------------
# May 4, 2021 Update
# This is maintained here for reference, but it seems like the networksetup script
# is capable of doing this, at least in Big Sur. I haven't tested this on older versions.
# See https://gist.github.com/mrpnelson/c65302efed6c18300fb28c8da87bc69a#gistcomment-3731567
# for details on using the native tooling
# ------------------------------------------------------------------------------------------
# A tool to set an existing remembered SSID as the most preferred network by script.
# Copyright (C) 2019 Paul Nelson
# This program is free software: you can redistribute it and/or modify it under the
# terms of the GNU General Public License as published by the Free Software Foundation,
# version 3.
# This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
# without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
# See the GNU General Public License for more details.
# https://www.gnu.org/licenses/gpl-3.0.html
# To run: mac_wipri "SSID"
# Wrap the SSID in double quotes.
# Requires sudo/administrative rights
if [ -z "$1" ]; then
echo "No SSID name supplied. Exiting.";
exit;
fi
SSIDNAME=$1
NETFILE="/Library/Preferences/\
SystemConfiguration/com.apple.airport.preferences.plist"
#Get SSID for desired network
SSIDID=`xpath $NETFILE "\
(//dict/dict/dict/string[text()='$SSIDNAME'])\
[1]/parent::dict/preceding-sibling::key[1]" \
2>/dev/null | sed -e 's/key/string/g'`
# Make sure the desired SSID exists in the list.
if [ -z "$SSIDID" ]; then
echo "No matching SSID value can be found in $NETFILE. Exiting.";
exit;
fi;
# Get the current preferred network list
ORDERLIST=`xpath $NETFILE "(//dict/key[text()='PreferredOrder'])\
[1]/following-sibling::array[1]" 2>/dev/null | sed '1d;$d'`
# Count number of current entries in the network list
NUMENTRIES=`echo "$ORDERLIST" | wc -l | sed -e 's/ //g'`
echo "There are $NUMENTRIES entries in preferred network list."
# Don't make changes if it's the only network
if [ "$NUMENTRIES" -le "1" ]; then
echo "Only one network, so no need to make priority changes. Exiting.";
exit;
fi;
# Get the row number for the first preferred network entry
PREFTOP=`/usr/bin/grep -n -x "$ORDERLIST" $NETFILE | \
cut -f1 -d: | head -n 1`
echo "Preferred network list starts at row $PREFTOP in $NETFILE."
# Get the row number of network we want to set as highest priority
SSIDTOMOVE=`echo "$ORDERLIST" | /usr/bin/grep -n $SSIDID | cut -f1 -d:`
if [ "$SSIDTOMOVE" -eq "1" ]; then
echo "$SSIDNAME is already top of the priority list. Exiting.";
exit;
fi
# Print the SSID and current row number for the entry
echo "$SSIDNAME is position number $SSIDTOMOVE in preferred ordering list."
# Now actually make the changes to the file
echo "Moving $SSIDNAME to top of preferred network list..."
printf %s\\n $(( PREFTOP - 1 + SSIDTOMOVE ))m$(( PREFTOP - 1)) w q \
| ed -s $NETFILE
# With knowledge of the starting row you could add additional networks
# and handle relative priorities for additional networks if desired.
# Verify that the change worked by checking current position in list
ORDERLIST=`xpath $NETFILE "(//dict/key[text()='PreferredOrder'])\
[1]/following-sibling::array[1]" 2>/dev/null | sed '1d;$d'`
NEWLOCATION=`echo "$ORDERLIST" | /usr/bin/grep -n $SSIDID | cut -f1 -d:`
echo "$SSIDNAME is now at position number $NEWLOCATION in preferred network list"
@iancd

This comment has been minimized.

Copy link

@iancd iancd commented Nov 1, 2019

Great script @mrpnelson. Would it be possible for you to remove the pcregrep dependancy so this works on a fresh macOS Catalina build?

@mrpnelson

This comment has been minimized.

Copy link
Owner Author

@mrpnelson mrpnelson commented Nov 1, 2019

@iancd - good catch on it breaking! Should be fixed now, replaced pcregrep and the -M multi-line option with grep and the -x line-regexp.

@iancd

This comment has been minimized.

Copy link

@iancd iancd commented Nov 5, 2019

@mrpnelson. First rate. Updated script working marvellously in my Catalina environment. Thank you for this. 👍🏻

@GabeShack

This comment has been minimized.

Copy link

@GabeShack GabeShack commented Mar 24, 2021

@mrpnelson Is there a good method to hardcode the value instead of calling it with $1?

@GabeShack

This comment has been minimized.

Copy link

@GabeShack GabeShack commented Mar 24, 2021

Never Mind, I figured it out, Hashed out the first if through the first fi and added my SSID after the $ with double quotes around it and its working fine. Thanks

@dstranathan

This comment has been minimized.

Copy link

@dstranathan dstranathan commented Apr 30, 2021

Has anyone tested this in macOS 11 Big Sur?

/Library/Preferences/SystemConfiguration/com.apple.airport.preferences.plist doesn't show any SSIDs but the Netowrk GUI shows 20+ SSIDs in my "Preferred Networks" list.

The data moved to a new file in Big Sur: /Library/Preferences/com.apple.wifi.known-networks.plist

@mrpnelson

This comment has been minimized.

Copy link
Owner Author

@mrpnelson mrpnelson commented May 4, 2021

@dstranathan this doesn't appear to work in Big Sur. That file can be parsed into a readable form with the python snippet below, but I don't see any associated ordering information, suggesting that ordering has been separated somewhere else. I've yet to find where, exactly, that's stored...

#!/usr/local/bin/python3
import plistlib, pprint
with open("/Library/Preferences/com.apple.wifi.known-networks.plist", 'rb') as f: pprint.PrettyPrinter(indent=4).pprint(plistlib.load(f))
@mrpnelson

This comment has been minimized.

Copy link
Owner Author

@mrpnelson mrpnelson commented May 4, 2021

@dstranathan simpler seems better. It looks like these can be changed with the following command sequence. It also renders the other/old code unnecessary (and maybe it always was?).

# Remove the network first. The password in the keychain is decoupled from this entry in the list, so will persist.
# You'll need to know the SSID, network interface, and the network security type for the network.

networksetup -removepreferredwirelessnetwork en0 "<SSID_NAME>"

# Now add back the network at index 0. This works at least for WPA2, and presumably all other types:

networksetup -addpreferredwirelessnetworkatindex en0 "<SSID_NAME>" 0 WPA2
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment