Skip to content

Instantly share code, notes, and snippets.

@jvarn
Created March 5, 2026 12:11
Show Gist options
  • Select an option

  • Save jvarn/65b300e244068637996ac1b0710c5717 to your computer and use it in GitHub Desktop.

Select an option

Save jvarn/65b300e244068637996ac1b0710c5717 to your computer and use it in GitHub Desktop.
Retrieve the MAC address of a network interface on a local or remote host (macOS or Linux)
#!/usr/bin/env bash
# -----------------------------------------------------------------------------
# getmacaddress.sh
#
# Retrieve the MAC address of a network interface on a local or remote host.
#
# The script connects to the specified host (via SSH if the host is not the
# local machine) and attempts to retrieve the MAC address of the specified
# network interface.
#
# Behaviour:
# - If no interface is specified, the script defaults to "en0".
# - If the interface exists, the MAC address is printed to stdout.
# - If the interface does not exist, the script lists available interfaces
# and prompts the user to select one interactively.
#
# The script supports both macOS and Linux systems:
# - macOS: uses `ifconfig` to obtain the MAC address
# - Linux: reads `/sys/class/net/<interface>/address`
#
# Rationale:
# Many modern Linux distributions no longer install the legacy
# `net-tools` package by default (which provides `ifconfig`). Rather
# than assuming its presence, the script reads the MAC address
# directly from `/sys/class/net`, which is part of the standard
# Linux kernel sysfs interface and is available on virtually all
# Linux systems.
#
# SSH is only used when the requested host differs from the local hostname
# (case-insensitive comparison).
#
# Usage:
# getmacaddress.sh <host> [interface]
#
# Examples:
# getmacaddress.sh computername1.local
# getmacaddress.sh computername2.local enp1s0
# getmacaddress.sh computername3.local en1
#
# Arguments:
# host Target hostname or SSH host alias
# interface Optional network interface (default: en0)
#
# Exit codes:
# 0 Success (MAC address printed)
# 1 Invalid input
# 2 Interface not found or MAC address could not be determined
#
# Requirements:
# - bash (compatible with macOS bash 3.2+)
# - ssh (for remote hosts)
# - ifconfig (macOS) or /sys/class/net (Linux)
#
# Installation (optional):
# To make the script available system-wide, copy it to a directory
# on your PATH, for example:
#
# cp getmacaddress.sh /usr/local/bin/getmacaddress
# chmod +x /usr/local/bin/getmacaddress
#
# You can then run it from anywhere, e.g.:
#
# getmacaddress computername.local
#
# (On macOS and many Linux systems, /usr/local/bin is already included
# in the default PATH.)
#
# Author: Jeremy Varnham https://github.com/jvarn
# License: MIT
# -----------------------------------------------------------------------------
usage() {
echo "Usage: $(basename "$0") <host> [interface]"
echo "Example: $(basename "$0") quark en1"
echo "If interface is omitted, en0 is used."
}
if [[ -z "$1" ]]; then
usage
exit 1
fi
HOST="$1"
INTERFACE="${2:-en0}"
LOCAL_HOST=$(hostname | tr '[:upper:]' '[:lower:]')
TARGET_HOST=$(echo "$HOST" | tr '[:upper:]' '[:lower:]')
# POSIX-sh compatible remote/local commands (NO [[ ... ]])
GET_MAC_CMD='
case "$OSTYPE" in
darwin*)
ifconfig '"$INTERFACE"' 2>/dev/null | awk "/ether/{print \$2; exit}"
;;
*)
cat /sys/class/net/'"$INTERFACE"'/address 2>/dev/null | head -n 1
;;
esac
'
LIST_IFACES_CMD='
case "$OSTYPE" in
darwin*)
ifconfig 2>/dev/null | awk "
/^[A-Za-z0-9._-]+:/{iface=\$1; sub(/:$/, \"\", iface)}
/ether[[:space:]]/{print iface}
" | sort -u
;;
*)
for p in /sys/class/net/*/address; do
iface=${p%/address}; iface=${iface##*/}
[ "$iface" = "lo" ] && continue
echo "$iface"
done | sort -u
;;
esac
'
run_cmd() {
# $1 = command string
if [[ "$TARGET_HOST" == "$LOCAL_HOST" ]]; then
sh -c "$1"
else
# run using /bin/sh on the remote, but keep the script POSIX-compatible
ssh "$HOST" "sh -c $(printf '%q' "$1")"
fi
}
MAC="$(run_cmd "$GET_MAC_CMD" | tr -d '\r' | head -n 1)"
if [[ -n "$MAC" ]]; then
echo "$MAC"
exit 0
fi
echo "Interface \"$INTERFACE\" does not exist on $HOST."
#mapfile -t IFACE_ARRAY < <(run_cmd "$LIST_IFACES_CMD" | tr -d '\r')
# Build IFACE_ARRAY (bash 3.2 compatible: no mapfile)
IFACE_ARRAY=()
while IFS= read -r line; do
[[ -n "$line" ]] && IFACE_ARRAY+=("$line")
done < <(run_cmd "$LIST_IFACES_CMD" | tr -d '\r')
if [[ ${#IFACE_ARRAY[@]} -eq 0 ]]; then
echo "(No interfaces with a MAC address were detected.)"
exit 2
fi
echo "Please choose one of the following interfaces:"
for i in "${!IFACE_ARRAY[@]}"; do
printf "%2d) %s\n" $((i+1)) "${IFACE_ARRAY[$i]}"
done
echo
read -p "Enter number: " CHOICE
if ! [[ "$CHOICE" =~ ^[0-9]+$ ]] || (( CHOICE < 1 || CHOICE > ${#IFACE_ARRAY[@]} )); then
echo "Invalid selection."
exit 1
fi
INTERFACE="${IFACE_ARRAY[$((CHOICE-1))]}"
MAC="$(run_cmd "
case \"\$OSTYPE\" in
darwin*)
ifconfig $INTERFACE 2>/dev/null | awk '/ether/{print \$2; exit}'
;;
*)
cat /sys/class/net/$INTERFACE/address 2>/dev/null | head -n 1
;;
esac
" | tr -d '\r')"
if [[ -n "$MAC" ]]; then
echo
echo "$MAC"
exit 0
fi
echo "Unable to determine MAC address."
exit 2
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment