18

Is there any reliable way to determine (programmatically) from within a bash script if it is being executed on a laptop or a desktop computer?

I could obviously just prompt the user to ask them, but that is pretty clunky.

2
  • 1
    I'd say why you need to know? Are you worried about battery life Feb 17 '15 at 22:29
  • 3
    The script is doing some system setup for the user, and part of that is configuring some power saving settings if the device is a laptop. Feb 17 '15 at 23:18
29

Looking at whether or not the system has a battery is not reliable - a UPS connected to the system (not just for power, but over USB as well for automatic shutdown and battery monitoring) may show up as a battery.

There is a nice reliable way however:

dmidecode --string chassis-type

On a laptop, this will return one of "Laptop", "Notebook" "Portable", or "Sub Notebook" (depending on what the manufacturer coded into the BIOS). There is a full list of possible values at "Identifying the Chassis Type of a Computer" in the Windows 2000 Scripting Guide - don't worry about it being a Microsoft TechNet page, this is not OS specific.

dmidecode can also get information about the hardware manufacturer, system serial number (sometimes), etc.

5
  • I have a UPS controlled via USB for automatic shutdown and battery monitoring with Network UPS Tool. It is does not show up as a "battery" on the Desktop. What configuration are you using that under which a UPS appears in /sys/module/battery?
    – John1024
    Feb 14 '15 at 7:35
  • This works better than the /sys/module/battery method: My two Ubuntu 14.04 desktops answer "Desktop" and "Low Profile Desktop", respectively, and the one with CentOS 6.5 says "Unknown". The one with CentOS 5.3 doesn't recognize the keyword "chassis-type". The Laptop I tried it on says "Notebook". But it's a drawback that you need root access. Feb 14 '15 at 9:36
  • I really like this answer!
    – Raphael
    Feb 14 '15 at 14:31
  • +1 for distribution independence. I tested it successfully on several machines. The only machine on which dmidecode gave a less than helpful answer was an Aspire netbook returned a chassis type of Other.
    – John1024
    Feb 15 '15 at 22:07
  • this answer requires sudo, so is not viable for things like .bashrc files. Querying the contents of /sys/class/dmi/id/chassis_type, which is just a single number, is much better (as another answer below pointed out).
    – xdavidliu
    Oct 5 '19 at 20:05
11

To avoid using sudo, you can read the contents of /sys/class/dmi/id/chassis_type, which will return the decimal value of the chassis type.

The meaning of the values can be seen in official documentation PDFs available at https://www.dmtf.org/standards/SMBIOS

The following table includes the information for smbios specification version 3.5.0 (22 Sep 2021).

Decimal value Hex value Meaning
1 01h Other
2 02h Unknown
3 03h Desktop
4 04h Low Profile Desktop
5 05h Pizza Box
6 06h Mini Tower
7 07h Tower
8 08h Portable
9 09h Laptop
10 0Ah Notebook
11 0Bh Hand Held
12 0Ch Docking Station
13 0Dh All in One
14 0Eh Sub Notebook
15 0Fh Space-saving
16 10h Lunch Box
17 11h Main Server Chassis
18 12h Expansion Chassis
19 13h SubChassis
20 14h Bus Expansion Chassis
21 15h Peripheral Chassis
22 16h RAID Chassis
23 17h Rack Mount Chassis
24 18h Sealed-case PC
25 19h Multi-system chassis
When this value is specified by an SMBIOS implementation, the physical chassis associated with this structure supports multiple, independently reporting physical systems—regardless of the chassis' current configuration. Systems in the same physical chassis are required to report the same value in this structure's Serial Number field.
For a chassis that may also be configured as either a single system or multiple physical systems, the multi-system chassis value is reported even if the chassis is currently configured as a single system. This allows management applications to recognize the multi-system potential of the chassis.
26 1Ah Compact PCI
27 1Bh Advanced TCA
28 1Ch Blade
An SMBIOS implementation for a Blade would contain a Type 3 Chassis structure for the individual Blade system as well as one for the Blade Enclosure that completes the Blade system.
29 1Dh Blade Enclosure
A Blade Enclosure is a specialized chassis that contains a set of Blades. It provides much of the non-core Computing infrastructure for a set of Blades (power, cooling, networking, and so on). A Blade Enclosure may itself reside inside a Rack or be a standalone chassis.
30 1Eh Tablet
31 1Fh Convertible
32 20h Detachable
33 21h IoT Gateway
34 22h Embedded PC
35 23h Mini PC
36 24h Stick PC
8
  • Source for the table? And is 'lunch box' a joke?!
    – OJFord
    Jul 14 '19 at 20:03
  • 1
    @OJFord I do not have a citation at this time. As far as 'lunchbox', it is a nickname give to a form factor. I've worked with a few lunchboxes and pizzaboxes before. While this link may not last years, you can see some very modern lunchbox computers theportablepc.com/portable-pc.html
    – demure
    Jul 14 '19 at 22:46
  • 1
    Grant's answer contains a citation from microsoft: docs.microsoft.com/en-us/previous-versions/tn-archive/…
    – demure
    Jul 14 '19 at 22:58
  • Thanks! Now I want one... But I suspect my wallet doesn't.
    – OJFord
    Jul 15 '19 at 6:04
  • This was the only solution that worked for me without needing to sudo. The battery-based solutions either said my ubuntu desktop was a laptop, or said my debian laptop was a desktop.
    – xdavidliu
    Oct 5 '19 at 19:54
9

Debian Solution:

To find whether a machine running Debian is a laptop, try:

[ -d /sys/module/battery ] && echo "Yes it's a laptop"

This approach does not require root privileges.

On other distributions, however, this directory seems to exist, at least in skeleton form, regardless of whether or not there is a battery. From the comments (below), these distributions include CentOS, Ubuntu, and the Ubuntu-derived distribution of Linux Mint.

More General Solution

Although it does not work on my Debian systems, the solution proposed by Alex reportedly works on Ubuntu & CentOS. Thus suggests, for greater generality, a possible combined solution:

[ -f /sys/module/battery/initstate ] || [ -d /proc/acpi/battery/BAT0 ] && echo "Yes it's a laptop"

This approach does not require root privileges.

More Details

On a Debian system with an actual battery, the /sys/module/battery directory contains many files. One such file is /sys/module/battery/initstate which contains the text live. On Ubuntu, however, these files do not exist even on actual laptops. Thus, it appears that the presence of the file /sys/module/battery/initstate can be used to test for a laptop running Debian.

On Debian systems that I tested, by contrast, the /proc/acpi/battery directory did not exist.

15
  • 1
    Isn't it possible that the second command could still return true in the case of a desktop with a UPS? Feb 13 '15 at 20:36
  • 3
    @PseudoPsyche I just tested it on a desktop with a UPS and it returned false (not a laptop).
    – John1024
    Feb 13 '15 at 20:41
  • 1
    What is that first command doing there?
    – AndreKR
    Feb 14 '15 at 2:11
  • 1
    Apparently my 4U IBM server with an APC SmartUPS plugged in over USB is a laptop. I certainly wouldn't want that thing on my lap all day! (ie, if it has a UPS plugged in and configured for shutdown/monitoring, that directory will exist)
    – Grant
    Feb 14 '15 at 3:31
  • 1
    @Chipperyman “Doesn't a UPS go between the wall socket and a computer power socket?” Yes, and many UPS setups—including consumer level—allow you to hookup a USB cable to get battery info and alerts on your desktop. Feb 14 '15 at 4:16
8

I'd check if the computer has a battery installed. And the following is one way to test:

if [ -d /proc/acpi/battery/BAT* ]; then
  echo has a battery
fi
8
  • This method gave the correct answer on all five computers I tried it on: two desktops with Ubuntu 14.04, one desktop with CentOS 5.3, one desktop with CentOS 6.5, and one laptop with Ubuntu 14.04. Also, it doesn't require root access. Of the three methods in the answers, my tests indicate that this may, tentatively, be the best one. Feb 14 '15 at 9:39
  • This works for me.
    – Raphael
    Feb 14 '15 at 14:38
  • This did not work on the two Debian laptops that I tested but +1 for working on a variety of other important distributions.
    – John1024
    Feb 15 '15 at 22:01
  • Doesn't work for me (Toshiba Notebook), because my battery is named BAT1. I don't know how many other possible names there might be.
    – Joe
    Feb 17 '15 at 6:42
  • @Joe Change BAT0 to BAT* -- it should detect all variations.
    – Alex
    Feb 17 '15 at 17:24
1

If checking for battery existence is good enough, you can use this shell function:

# Checks whether system is a laptop.
#
# @returns {bool}   true if system is a laptop.
function is_laptop() {
    local d
    for d in /sys/class/power_supply /proc/acpi/battery; do
        [[ -d "$d" ]] && find $d -mindepth 1 -maxdepth 1 -name 'BAT*' -print0 -quit 2>/dev/null | grep -q . && return 0
    done

    # note we're checking /sys/class/power_supply/battery/status for WSL
    for d in /sys/class/power_supply/battery/status /sys/module/battery/initstate; do
        [[ -f "$d" ]] && return 0
    done

    return 1
}

Have been using this on Debian for years. Note this works also for Debian running in WSL or virtualbox.

Edit: generalized from other answers in this thread to catch more cases.

0

Another solution that does not require sudo:

hostnamectl status | grep Chassis | cut -f2 -d ":" | tr -d ' '

Will output laptop or desktop.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.