-
-
Save mrpnelson/c65302efed6c18300fb28c8da87bc69a to your computer and use it in GitHub Desktop.
#!/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" |
@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))
@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
@mrpnelson Looks like this isn't working properly on 11.6 or above since they changed the plist which now resides in /Library/Preferences/com.apple.wifi.known-networks.plist. I tried to change the netfile to the new path but im guessing the raw data is also different.
@GabeShack does the method provided here work for you? I think with a known SSID, that's the best way without needing external scripts.
I think it could but I’ll have to test if when removing it first it disconnects then before re adding it. If it is disconnecting it on the first command, then this method won’t work for me.
@mrpnelson That also only adds WPA2/3 personal and not enterprise. So something not quite right about it. Same command with WPA2E adds the enterprise. If this truly doesnt touch the keychain, then it probably wont create problems for disconnection if we remove and re-add it. Its just too bad there isnt a way to directly edit the priority list to just assign it the first position without first removing it.
@GabeShack I tested this, and it seems to work fine for me with WPA2 Enterprise networks as well. Per the manpage:
Usage: networksetup -addpreferredwirelessnetworkatindex [password]
Add wireless network named to preferred list for at .
For security type, use OPEN for none, WPA for WPA Personal, WPAE for WPA Enterprise,
WPA2 for WPA2 Personal, WPA2E for WPA2 Enterprise, WEP for plain WEP, and 8021XWEP for 802.1X WEP.
If a password is included, it gets stored in the keychain.
So, assuming your interface is en0 and your SSID is MyNet, you'd run:
networksetup -removepreferredwirelessnetwork en0 "MyNet"
networksetup -addpreferredwirelessnetworkatindex en0 "MyNet" 0 WPA2E
Perhaps give that a try and let me know? While plutil allows us to change the plist into an editable format (and convert back), the overall structure of that plist has now changed, meaning a complete overhaul would be necessary to the original code. Thus if native tools are an option, that seems the best path for long-term supportability.
Thanks to this post, I was able to compile a script to set your desired Wi-Fi on Priority every time the system restarts.
https://github.com/joshikavan92/macOSWi-Fi/blob/main/set_ssid_priority.sh
@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
This won't work for 802.1x networks configured via config profile with things like certificates.
I think our best bet would be to keep going down this path and figure out how to grab the key/dict pair of the selected network and reorder it in the plist. I just wish I was more versed in python to help.
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