33

Situation: I'm using multiple monitors and I want to get their names in bash. Currently I'm using Ubuntu 10.04.

I know about xrandr. From it I can get only statistics data. What I want is to read all monitor names in an array to work with them.

Is there a clear way to do that without cutting names from some kind of string? A clear way would be reading them from file. A not clear way would be to pipe xrandr output to some sort a function to cut names out from it.

5
  • As far as I know you need to get that from driver specific APIs. There used to be something in nvidia. What card do you have? Or did you need something generic? Commented May 8, 2012 at 14:35
  • 1
    @Miquel My video card is ATI Radeon HD 5000. Better of course would be to get more generic solution. But specific solution for my current machine also will do. Commented May 8, 2012 at 19:16
  • I agree that getting certain properties by parsing and decoding the output of xrandr --prop or xrandr --verbose is not a clear way, as the output formatting of xrandr is subject to change and is undocumented. I wish xrandr had ways to read individual properties of a given output (e.g. like exiftool has ways to read individual meta information tags of given files). Commented Apr 5, 2015 at 12:07
  • I am not sure what kind of monitor names you want. Would it be enough to get the output names? I have noticed, that the EDID information of a laptop computer may not have a monitor name for the integrated display, but it may have some brand name and part name declared there anyway. Commented Apr 5, 2015 at 12:08
  • There is similar topic in unix.stackexchange.com. Commented May 22, 2015 at 7:10

8 Answers 8

31

Tested on Ubuntu 16.04, 18.04. (I know its too late to answer but this solution is relevant today)

$ sudo apt-get install -y hwinfo ... $ hwinfo --monitor --short monitor: SONY TV AUO LCD Monitor 

I have two monitors attached. One with the laptop and the other is an external display. As soon as the external monitor is plugged-in or out, this command reflects the change. You continuously need to poll. Removing the --short option gives more detailed information.

You can poll the state with the following background job:

$ while true; > do > hwinfo --monitor --short; > sleep 2; > done >> monitor.log & 

The while true loop runs infinite times. The sleep 2 pauses each iteration of the loop for 2 seconds. And the output of hwinfo --monitor --short is appended to monitor.log. This log file can give you the activity history of monitor plug-in and plug-out.

FYI: I am using a background (daemon) python script using the above command (and other similar ones) to detect if someone is doing some HW plug-ins and plug-outs with the systems in the computer lab. If so, I get appropriate notifications that someone plugged-out/in a monitor, mouse or keyboard in almost real-time!

More info about hwinfo command is here. Its man page is also a good source.

Sign up to request clarification or add additional context in comments.

2 Comments

This is the simplest and straight to the point
Using this solution, the command hwinfo --monitor --short returns no results. Why?
31

Inspired by Beni's answer, this will read the EDID data using xrandr and extract the monitors names according to the EDID specification, with no need of any external tools like parse-edid:

#!/bin/bash while read -r output hex conn; do [[ -z "$conn" ]] && conn=${output%%-*} echo "# $output $conn $(xxd -r -p <<< "$hex")" done < <(xrandr --prop | awk ' !/^[ \t]/ { if (output && hex) print output, hex, conn output=$1 hex="" } /ConnectorType:/ {conn=$2} /[:.]/ && h { sub(/.*000000fc00/, "", hex) hex = substr(hex, 0, 26) "0a" sub(/0a.*/, "", hex) h=0 } h {sub(/[ \t]+/, ""); hex = hex $0} /EDID.*:/ {h=1} END {if (output && hex) print output, hex, conn} ' | sort ) 

Uses awk to precisely extract the monitor name only, and no extra garbage from the EDID, hence "magic numbers" like 000000fc00, 26 and 0a. Finally uses xxd to convert from hex to ASCII, printing one monitor name per line.

Based on this solution I made a handy script to switch monitors, which can also be used to simply list monitor info:

$ monitor-switch --list Connected monitors: # DFP5 HDMI HT-R391 # DFP7 DVI-I DELL U2412M $ monitor-switch --list Connected monitors: # DisplayPort-1 DisplayPort DELL U2412M # DisplayPort-3 DisplayPort DELL U2415 # HDMI-A-2 HDMI LG TV 

9 Comments

I tested the inline script by my monitor and it prints nothing. I inspected the EDID and noticed that it has two Monitor Descriptors tagged as FCh, the first of which is L1715S and the second of which is empty. On my laptop there is no such descriptor for the integrated display, but two descriptors tagged as FEh, which apparently contain brand name CPT and model name CLAA102NA0A.
At least one FCh entry is mandatory by the spec, so it's weird your laptop does not contain one... FEh stands for "unspecified text", basically a free text field, so I cannot rely on it containing relevant information. About printing nothing, open a question pasting both EDIDs so we can tweak the script for your case.
Maybe the laptop display has no name since it is not a separate customer product.
A couple of real world sample EDIDs for testing: 00ffffffffffff001e6d6f432c340400110f01036e221b78ea2ee5a4574a9c25115054a56b80314f454f614f81800101010101010101302a009851002a4030701300520e1100001e000000fd00384b1e530e000a202020202020000000fc004c31373135530a202020202020000000fc000a2020202020202020202020200098, 00ffffffffffff00320c000000000000000f0102801e16780a74b09657548b282550540000000101010101010101010101010101010164190040410026301888360030e410000018000000000000000000000000000000000000000000fe004c475068696c6970734c43440a000000fe004c503135305830382d544c414100a3
@IvanVučica: Nice catch! I've fixed the script, no need for echo anymore. Thanks for pointing out this bug!
|
11

sudo get-edid didn't work for me. (EDIT: now works on another computer, Lubuntu 14.10; I'd blame BIOS differences but that's a random guess...)

Anyway under X, xrandr --verbose prints the EDID block. Here is a quick and dirty way to extract it and pass to parse-edid:

#!/bin/bash xrandr --verbose | perl -ne ' if ((/EDID(_DATA)?:/.../:/) && !/:/) { s/^\s+//; chomp; $hex .= $_; } elsif ($hex) { # Use "|strings" if you dont have read-edid package installed # and just want to see (or grep) the human-readable parts. open FH, "|parse-edid"; print FH pack("H*", $hex); $hex = ""; }' 

3 Comments

For Intel cards, edid files are provided in /sys. find /sys -name edid. This does not look to be the case for ATI. Can't verify for NVidia.
For the xrandr in Ubuntu 12.04, replace EDID: for EDID_DATA: in line 3. It works great when |strings is used, as per the in-code comment.
I found out that xrandr knows current EDID better than the file found by the command @Dave told, if you change monitor on fly.
2

You may try ddcprobe and/or get-edid

$ sudo apt-get install xresprobe read-edid $ sudo ddcprobe $ sudo get-edid 

2 Comments

This didnt output needed. xrandr would output window names from xorg.conf file. Those names are what I expected.
Adding parse-edid after get-edid makes the output more meaningful.This worked for me sudo get-edid | parse-edid If you have multiple monitors you can display details using sudo get-edid -b 0 | parse-edid --> for 1st monitor. sudo get-edid -b 1 | parse-edid --> for 2nd monitor.
2

If you don't want to parse xrandr output, write a C program using libXrandr that gets only what you want. If all you want to do is to query information, it can be done quickly. Read this document.

If you want to get the real monitor name, an alternative to @dtmilano's solution is to get the EDID property of the monitor using libXrandr and then manually parse it and print (read the EDID specification).

xrandr source code.

1 Comment

If you're writing a C program to do this, you can get the monitor vendor name from the PNP ID (e.g. "SAM" => "Samsung Electric Company") really easily using this: github.com/golightlyb/PNP-ID
2

I know this is a dirty way, but it gives me some monitor model name even better than sudo get-edid|parse-edid. It reads information in arrays, and outputs it in a way that can be read like you would read a file. You may modify it according to your needs.

#!/bin/bash # # # get-monitors.sh # # Get monitor name and some other properties of connected monitors # by investigating the output of xrandr command and EDID data # provided by it. # # Copyright (C) 2015,2016 Jarno Suni <[email protected]> # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. See <http://www.gnu.org/licenses/gpl.html> set -o nounset set -o errexit # EDID format: # http://en.wikipedia.org/wiki/Extended_Display_Identification_Data#EDID_1.3_data_format # http://read.pudn.com/downloads110/ebook/456020/E-EDID%20Standard.pdf declare -r us=';' # separator string; # If EDID has more than one field with same tag, concatenate them, # but add this string in between. declare -r fs=$'\x1f' # Field separator for internal use; # must be a character that does not occur in data fields. declare -r invalid_edid_tag='--bad EDID--' # If base EDID is invalid, don't try to extract information from it, # but assign this string to the fields. # Get information in these arrays: declare -a outs # Output names declare -a conns # Connection type names (if available) declare -a names # Monitor names (but empty for some laptop displays) declare -a datas # Extra data; may include laptop display brand name # and model name declare -i no # number of connected outputs (to be counted) # xrandr command to use as a source of information: declare -r xrandr_output_cmd="xrandr --prop" hex_to_ascii() { echo -n "$1" | xxd -r -p } ascii_to_hex() { echo -n "$1" | xxd -p } get_info() { no=0 declare OIFS=$IFS; IFS=$fs while read -r output conn hexn hexd; do outs[no]="${output}" conns[no]="${conn}" names[no]="$(hex_to_ascii "$hexn")" datas[no]="$(hex_to_ascii "$hexd")" (( ++no )) done < <(eval $xrandr_output_cmd | gawk -v gfs="$fs" ' function print_fields() { print output, conn, hexn, hexd conn=""; hexn=""; hexd="" } function append_hex_field(src_hex,position,app_hex, n) { n=substr(src_hex,position+10,26) sub(/0a.*/, "", n) # EDID specification says field ends by 0x0a # (\n), if it is shorter than 13 bytes. #sub(/(20)+$/, "", n) # strip whitespace at the end of ascii string if (n && app_hex) return app_hex sp n else return app_hex n } function get_hex_edid( hex) { getline while (/^[ \t]*[[:xdigit:]]+$/) { sub(/[ \t]*/, "") hex = hex $0 getline } return hex } function valid_edid(hex, a, sum) { if (length(hex)<256) return 0 for ( a=1; a<=256; a+=2 ) { # this requires gawk sum+=strtonum("0x" substr(hex,a,2)) # this requires --non-decimal-data for gawk: #sum+=sprintf("%d", "0x" substr(hex,a,2)) } if (sum % 256) return 0 return 1 } BEGIN { OFS=gfs } /[^[:blank:]]+ connected/ { if (unprinted) print_fields() unprinted=1 output=$1 } /[^[:blank:]]+ disconnected/ { if (unprinted) print_fields() unprinted=0 } /^[[:blank:]]*EDID.*:/ { hex=get_hex_edid() if (valid_edid(hex)) { for ( c=109; c<=217; c+=36 ) { switch (substr(hex,c,10)) { case "000000fc00" : hexn=append_hex_field(hex,c,hexn) break case "000000fe00" : hexd=append_hex_field(hex,c,hexd) break } } } else { # set special value to denote invalid EDID hexn=iet; hexd=iet } } /ConnectorType:/ { conn=$2 } END { if (unprinted) print_fields() }' sp=$(ascii_to_hex $us) iet=$(ascii_to_hex $invalid_edid_tag)) IFS="$OIFS" } get_info # print the colums of each display quoted in one row for (( i=0; i<$no; i++ )); do echo "'${outs[i]}' '${conns[i]}' '${names[i]}' '${datas[i]}'" done 

4 Comments

Great script! Not sure though what the fourth parameter should be, it stays empty with my monitors. However, if I change 000000fe00 to 000000ff00, it shows my monitors serial numbers. This is great for detecting which monitor is hooked up to what connector. (000000fe00 according to wiki is an unspecified text field.)
@Geeklab Thanks. 000000fe00 is the offset to unspecified text according to the standard, but IIRC it contained something meaningful information of some old monitor I had, so I took it in. This version uses GNU awk (gawk) which suits better for this task, but I have made also some more portable version of this. I also added functionality to get display dimensions in my local copy. Maybe I will publish it in e.g. GitHub someday.
@jarno: please ping me if you do!
@Geeklab in my system the "000000ff00" field is empty for all monitors. In EDID 1.4. there is also serial number at bytes 12-15 of the raw data, but it is not the same I suppose.
0

You're looking for EDID information, which is passed along an I²C bus and interpreted by your video driver. As dtmilano says, get-edit from ddcprobe should work.

You can also get this information by logging your X start:

startx -- -logverbose 6 

Years ago, I used a package called read-edid to gather this information.

The read-edid package may be available in Ubuntu already, according to this blog post from 2009.

Comments

0
 xrandr | jc --xrandr | jq '[.screens[0].devices[] | .device_name] | join(",")' 

1 Comment

hwinfo --monitor --short retrieves the correct monitor names, however xrandr | jc --xrandr | jq '[.screens[0].devices[] | .device_name] | join(",")' does not retrieve the correct monitor names on my Ubuntu.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.