Mac address commands: why two of them disagree
Someone asks for the address of a Mac. A command gets run, a value gets sent, and the person on the other end says it does not match what they see. Nothing was mistyped. macOS reports two different addresses for the same Wi-Fi interface depending on which command asks, and both are correct answers to slightly different questions. Everything below was run on macOS 26.6.2.
Decide which address is wanted before typing anything
The word covers two unrelated jobs on a Mac, and they need different tools.
One is the hardware network address, the value a network administrator wants when registering a device or reading a lease table. The other is a file's address on disk, the full path needed to paste into a script, an upload dialog, or a message to a colleague. Search results mix the two because the words are the same. Half the frustration in this area comes from running a networking command when a path was wanted, or the reverse.
Both are covered below, networking first because that is where the surprising behaviour lives. The quickest way to tell which one a task needs is to ask who receives the answer. A network administrator, a form, or a router configuration page wants the networking value. A script, a colleague, or an upload dialog wants the path. Nothing else about the request distinguishes them, and the words used to ask will not.
Two commands, two different answers
Ask two built in commands about the same Wi-Fi interface and the values do not match:
$ networksetup -getmacaddress Wi-Fi
Ethernet Address: 70:8c:f2:xx:xx:xx (Hardware Port: Wi-Fi)
$ ifconfig en0 | grep ether
ether 5e:65:19:xx:xx:xx
The first reports the address burned into the card. The second reports the address the Mac is currently presenting to the network, which by default is a per network private address rather than the hardware one. system_profiler SPAirPortDataType agrees with ifconfig. Reading the registry shows both sitting side by side:
$ ioreg -l | grep -i IOMACAddress
"IOMACAddress" = <5e6519xxxxxx>
"IOMACAddress" = <708cf2xxxxxx>
When a network administrator says the submitted address does not appear on their equipment, the usual cause is that ifconfig was used and the private address got sent. For registering a device, networksetup -getmacaddress is the value that stays put. For debugging what the router is actually seeing right now, ifconfig is the one that matches.
Telling the two apart without a second command
Any address can be classified from its first byte. The second lowest bit of that byte is the locally administered flag. Set means the address was generated rather than assigned to a manufacturer.
In practice, read the second hex digit of the address. If it is 2, 6, A, or E, the address is locally administered, which on a Mac almost always means a private Wi-Fi address. In the pair above, 70 gives a second digit of 0 and is a real hardware address, while 5e gives E and is generated. This works on any address from any source, including one pasted into a chat window by somebody else, which makes it a fast way to check whether the value being discussed is even the kind of value the conversation needs.
What Apple documents about the changing address
The behaviour is deliberate and documented:
By default, your device improves privacy by using a different MAC address for each Wi-Fi network. This unique MAC address is your device's private Wi-Fi address, which it uses for that network only. Source: support.apple.com
The same page states that the setting lives in System Settings under Wi-Fi on macOS Sequoia 15 and later, and offers three positions. Off makes the device use its hardware address. Fixed keeps one private address for that network. Rotating changes to a different private address every two weeks. That last option is worth knowing about before filing a support ticket, because an address recorded a month ago can legitimately have stopped matching without anyone touching the machine.
| Command | Reports | Best used for |
|---|---|---|
networksetup -getmacaddress Wi-Fi |
Hardware address | Registering a device, filling in a form |
ifconfig en0 |
Address currently in use | Matching what the router or switch sees |
system_profiler SPAirPortDataType |
Address currently in use | A readable summary alongside the network name |
arp -a |
Addresses of other devices on the network | Finding a printer, a camera, a device with no screen |
Finding the address of something other than this Mac
Interface names are not fixed across machines, so guessing en0 wastes time. Ask which interface actually carries traffic:
$ route -n get default
gateway: 192.168.1.1
interface: en7
On the machine used here the default route goes over en7, not en0, because a Thunderbolt Ethernet adapter is attached. Running ifconfig en0 there would have reported an interface that is up but idle.
For other devices, arp -a lists what this Mac has recently talked to, with each entry showing a hostname or IP address, its hardware address, and the interface it was seen on. The list only contains devices already contacted, so pinging the target first is what makes it appear. This is the practical route to the address of a printer or a headless device that offers no screen to read it from.
Interfaces that are not Wi-Fi
networksetup -listallhardwareports prints every port with its device name and address, and on a machine with adapters attached the list is longer than expected. A single Mac here reported Thunderbolt Ethernet, several adapter entries, and Wi-Fi, each with its own address. Anyone filling in a form that asks for "the MAC address" has to know which port the machine will actually connect through, because registering the wrong one produces a device that is registered and still cannot connect.
Reading the whole list once, rather than grabbing whatever the first command returned, takes a few seconds and settles it. Where a docking station is involved, the address that matters often belongs to the dock rather than to the Mac, which means it changes the moment the machine is used at a different desk. That is a configuration fact worth writing down next to the registration, because a year later nobody remembers why the laptop only works in one room.
The other kind of address: a file's path
For the second meaning, three commands cover almost everything. pwd prints where the shell currently is. realpath turns a relative or messy path into an absolute one, following symbolic links on the way:
$ realpath tmp
/Users/admin/dev/Cursor/atsoho-blog/tmp
Searching by name is mdfind, which queries the Spotlight index rather than walking the disk, so it returns in a moment on a volume that find would grind through:
$ mdfind -onlyin ~/projects -name "chunks2"
$ mdfind "kMDItemFSName == 'WRITER-MAC.md'" -onlyin ~/projects
The second form matches an exact file name rather than any substring, which matters when the name is short. mdls prints the indexed attributes of a single file, including its type and size, which is how to check what Spotlight thinks something is when a search fails to return it. In the other direction, open -R selects a path in Finder, turning a result from the shell into a highlighted item without any dragging.
Searching contents, not just names
The index holds more than file names, and searching contents uses the same command with an attribute instead of -name:
$ mdfind -onlyin ~/projects "kMDItemTextContent == '*ditto*'"
That returns files containing the word rather than files named after it, which is the difference between finding a document and finding the folder someone once labelled with the topic. Attribute queries also compose, so content, kind, and date can be combined in one expression. mdls on any single file lists the attribute names available, which is the practical way to discover what can be queried rather than memorising them.
Passing results onward needs one habit. Paths contain spaces, and a plain pipeline breaks on the first one. mdfind -0 separates results with a null byte and xargs -0 reads them back the same way, so the pair survives any name:
$ mdfind -0 -onlyin ~/projects -name "report" | xargs -0 ls -l
The same applies to a path pasted from Finder. Dragging a file into a Terminal window inserts its path already escaped, which is faster and more reliable than typing it, and open -R sends a path in the other direction. Where the search has to continue away from the desk, the From iPhone and iPad page covers picking the same session up on another device rather than starting the hunt again.
When the search returns nothing at all
A search that finds a file which certainly exists usually means the volume is not indexed. That state is readable:
$ mdutil -a -s
/:
Indexing disabled.
/System/Volumes/Data:
Indexing enabled.
/Volumes/BAND 1.10.17:
Indexing disabled.
Three volumes, two different answers. The system volume being disabled is normal and harmless. The external drive being disabled is the one that bites, because mdfind will silently return nothing for everything stored on it, forever, with no error to explain why. External drives frequently arrive in this state and stay there.
Once that is known, the fix is a choice rather than a mystery. Either index the volume, or accept it and search with find, which reads directories directly and does not care about the index. Guessing between the two is what wastes the afternoon. Keeping the folder view and the shell in one window is what makes checking the index state a five second detour instead of a task of its own, which is what the Features page is about.
Why the two meanings keep colliding
It is tempting to treat the ambiguity as a quirk of language, but the overlap has a practical consequence worth naming. Both kinds of address are values that get copied out of a terminal and pasted somewhere else, usually into a message to another person, and both fail in the same quiet way. The value is correct at the moment it is read and wrong by the time it is used.
A private Wi-Fi address is correct until the network rotates it. A file path is correct until the file moves, and files move constantly during a project. In both cases the recipient receives something that looks authoritative, and the failure surfaces later as a device that will not connect or a link that leads nowhere.
The handling is the same for both. Send the stable form rather than the current form. For networking that means the hardware address from networksetup, not the live value from ifconfig. For files it means a path anchored somewhere that does not move, and a check that the file is actually there at the moment of sending rather than the moment it was found. realpath resolving without error is that check, and it costs one command.
This is also where a search habit pays off. Anyone who can locate a file by name in a second stops caching paths in notes, and a path that is never cached is never stale. The same applies on the network side, where knowing the two commands well enough to run either on demand removes the temptation to write the answer down once and trust it for a year.
What to change first
Decide which address the question actually needs before running anything, then pick the matching command from the table above rather than the first one a search result offers. If a search for a file comes back empty, run mdutil -a -s before doubting the file. A window that holds the folder, the terminal, and the answer together removes most of the switching those checks otherwise cost, which is the shape Atriens is built to.
Frequently asked questions
Which address should be given to a network administrator?
The one from networksetup -getmacaddress, because it is the hardware address and it does not change. The value shown by ifconfig is normally the private Wi-Fi address for that particular network, and on the rotating setting it changes every two weeks, so a registration made with it stops working without warning.
Why does an address recorded last month no longer match?
Private Wi-Fi addresses can rotate. Apple documents a Rotating setting that moves to a different private address every two weeks, and it is the default when joining a network with weak security or none. Nothing on the Mac was changed. Switching that setting to Off for the network in question makes the device present its hardware address instead.
How can the address of a printer or a device with no screen be found?
Contact it first, then read the table. Pinging its IP address puts it into the local cache, and arp -a then lists it with its hardware address and the interface it was seen on. Devices that have not been contacted recently will not appear, which is why the ping comes first.
Why does a file search return nothing even though the file is there?
The volume holding it is probably not indexed. mdutil -a -s prints the state of every mounted volume, and external drives are often listed as disabled. While a volume is unindexed, index based searching returns nothing for it and reports no error. Searching that volume with find works regardless of the index.