Im looking for a way to use the macOS networksetup command (and some string/line filtering mojo) to output all SSIDs from the Preferred Networks, and then determine what index my corp SSID is located at (and then take action depending on what index value it has).


admin@mac1 ~ % networksetup -listpreferredwirelessnetworks en0
Preferred networks on en0:
    Hipster Cafe
    Hilton Hotels
    Marriot - Public-5G

You will see each line shows an SSID. 'Denny's' is at index 0 (top) and, therefore, is the prioritized SSID.

Likewise, you will see my Corporate network ('HOME-OFFICE') is at the bottom (index 7 of 7).

How can I get the index value using a shell script? I have tried parsing the output and then building/filtering/appending a list using tools such as wc, grep, etc but haven't gotten the logic right thus far.

I already have the logic to move my corporate SSID up to index 0, but I only want to run that logic if the SSID 'HOME-OFFICE' is NOT already at index 0 - which I can't seem to figure out.

  • Why do you need to change the priority? Why by scriot rather than just dragging them into a new order? Are any of these in 'earshot' of another? If not, then the first available in the list will be chosen.
    – Tetsujin
    May 1, 2021 at 18:16
  • Found this article on the airport app that might help.
    – Mr R
    May 2, 2021 at 4:44

1 Answer 1


Formulating the problem in terms of “which index does my corporate network have?” makes the problem more complicated. Since you only want to know whether it's at the top of the list, just check whether the top of the list is your corporate network.


Here's a way to put the network names into an array in zsh. This uses three nested parameter expansion constructs around a command substitution:

  • ${(f)$(…)} splits the output of the command substitution into lines (f flag).
  • ${(@)…##[[:space:]]##} strips off the prefix matching the pattern [[:space:]]##, meaning one or more whitespace characters. ([[:space:]]#, meaning zero or more whitespace characters, would be equivalent, since removing an empty string has no effect.) The goal is to strip the leading tab. ${(@)…#$'\t'} would work too, but would be fragile in case a different version of macOS uses a different amount of spacing. The pattern needs setopt extended_glob, which is off by default. The @ flag ensures that the data is processed as a list of strings (list of lines from the previous step) and not as a single string.
  • "${(@)…[2,-1]}" selects the elements of the array from the second one (zsh arrays start at 1) to the last one (-1). This removes the “Preferred networks on …” line. The @ flag ensures that each line ends up in a separate array element. The double quotes ensure that spaces inside a network name do not cause each word of a name to end up in a separate array element.
setopt extended_glob
networks=("${(@)${(@)${(f)$(networksetup -listpreferredwirelessnetworks en0)}##[[:space:]]##}[2,-1]}")

Now you can check whether the first element is what you want:

if [[ $networks[1] != "HOME-OFFICE" ]]; then

If you do want the (1-based) index of a network name, you can use the i array subscript flag.

echo $networks[(i)"HOME-OFFICE"]


You can use sed to extract a specific line by number. Line numbers start at 1. Use the -n command line flag to suppress printing and the p command to print the desired line, or use the d command to delete all lines except the desired one. Use the s command to strip off leading whitespace; note that there is a literal tab character and a space inside the brackets. You can add the suffix p to the s command to print its output without a separate p command.

preferred_network=$(networksetup -listpreferredwirelessnetworks en0 | sed -n '2s/^[  ]*//p')


preferred_network=$(networksetup -listpreferredwirelessnetworks en0 | sed -n '2!d; s/^[  ]*//')

You can get the 2-based index of an element by name with sed by applying the = command to the line(s) matched by a regular expression.

line_number=$(networksetup -listpreferredwirelessnetworks en0 | sed -n 's/^[     ]*//; /^HOME-OFFICE$/=')
zero_based_index=$((line_number - 2))


You can use awk to extract a specific line by number. Line numbers start at 1, and the number of the current line is in the NR variable. After matching the desired line, remove the leading whitespace with the sub command, then print the line. Awk recognizes \t to mean a tab character.

preferred_network=$(networksetup -listpreferredwirelessnetworks en0 | awk 'NR==2 {sub(/^[\t ]*/, ""); print}')

If you want the number of a line with a specific content, you can match the line with a regular expression or by doing a string comparison ($0 contains the whole line without a terminating newline character), then print NR.

home_office_zero_based_index=$(networksetup -listpreferredwirelessnetworks en0 | awk '{sub(/^[\t ]*/, "")} $0 == "HOME-OFFICE" {print NR - 2})'


home_office_zero_based_index=$(networksetup -listpreferredwirelessnetworks en0 | awk '/^[\t ]HOME-OFFICE$/ {print NR - 2})'

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .