Reputation: 44347
How can I detect from a shell script that it is running on M1 Apple hardware?
I want to be able to run a command-line command so that I can write an if
-statement whose body will only be executed when run on a mac with an M1 processor (and at least macOS Big Sur, naturally).
Upvotes: 78
Views: 45479
Reputation: 38657
Let's address properly the situation where the command is run on a Rosetta environment (example: right-click Terminal.app in Finder > Info > Open with Rosetta).
The solutions with uname -m
, uname -p
and arch
will all fail in this case.
The solution with sysctl -n machdep.cpu.brand_string
is sensible to arbitrary brand naming evolution.
So what we really want is uname -s
being "Darwin" combined with uname -v
containing "ARM64". Do NOT use uname -a
, which is prone to errors if the name of the machine itself contains "ARM64".
if [[ "$(uname -s)" = Darwin && "$(uname -v)" = *ARM64* ]]; then
echo 'Apple Silicon'
else
echo 'something else'
fi
This solution works properly with and without Rosetta, and is probably future proof.
Upvotes: 2
Reputation: 1
/usr/bin/arch is all you need. Why complicate things when there's already a program to do this for you.
Upvotes: -1
Reputation: 7530
I found that sysctl -n machdep.cpu.brand_string
reported Apple M1
even though the process was run under Rosetta.
Update: be prepared for Apple M1 Pro
, Apple M2
, Apple M2 Max
etc.!
Upvotes: 36
Reputation: 44347
uname -m
will return arm64
as opposed to x86_64
if [[ $(uname -m) == 'arm64' ]]; then
echo M1
fi
or, as @chepner suggested
uname -p
will return arm
as opposed to i386
if [[ $(uname -p) == 'arm' ]]; then
echo M1
fi
yet another tool is arch
:
if [[ $(arch) == 'arm64' ]]; then
echo M1
fi
Upvotes: 106
Reputation: 48620
When using the native shell say /bin/bash -i
or /bin/zsh -i
, Klas Mellbourn's answer works as expected.
If using a shell that was installed via an Intel/Rosetta Homebrew installation, then uname -p
returns i386
, and uname -m
returns x86_64
, as indicated by Datasun's comment.
To get something that works across environments (Apple Silicon Native, Rosetta Shell, Linux, Raspberry Pi 4s), I use the following from the dorothy dotfile ecosystem:
is-mac && test "$(get-arch)" = 'a64'
If you aren't using dorothy, the relevant code from dorothy is:
https://github.com/bevry/dorothy/blob/1c747c0fa6bb3e6c18cdc9bae17ab66c0603d788/commands/is-mac
test "$(uname -s)" = "Darwin"
https://github.com/bevry/dorothy/blob/1c747c0fa6bb3e6c18cdc9bae17ab66c0603d788/commands/get-arch
arch="$(uname -m)" # -i is only linux, -m is linux and apple
if [[ "$arch" = x86_64* ]]; then
if [[ "$(uname -a)" = *ARM64* ]]; then
echo 'a64'
else
echo 'x64'
fi
elif [[ "$arch" = i*86 ]]; then
echo 'x32'
elif [[ "$arch" = arm* ]]; then
echo 'a32'
elif test "$arch" = aarch64; then
echo 'a64'
else
exit 1
fi
Jatin Mehrotra's answer on a duplicate question gives details on how to get the specific CPU instead of the architecture. Using sysctl -n machdep.cpu.brand_string
outputs Apple M1
on my M1 Mac Mini, however outputs the following on a Raspberry Pi 4 Ubuntu Server:
> sysctl -n machdep.cpu.brand_string
Command 'sysctl' is available in the following places
* /sbin/sysctl
* /usr/sbin/sysctl
The command could not be located because '/sbin:/usr/sbin' is not included in the PATH environment variable.
This is most likely caused by the lack of administrative privileges associated with your user account.
sysctl: command not found
> sudo sysctl -n machdep.cpu.brand_string
sysctl: cannot stat /proc/sys/machdep/cpu/brand_string: No such file or directory
Upvotes: 13