29

I have a text status bar on a tiling window manager and I am using tcl to feed information to it. At the moment I need a command line that output the volume level 0% to 100%. I am using Arch Linux.

3
  • 1
    Looks like you should be able to do it by parsing /var/lib/alsa/asound.state.
    – jordanm
    Sep 5, 2013 at 19:22
  • 1
    Note: in the future, saying you're using Arch isn't really relevant. What actually matters is what sound subsystem you're using, e.g. ALSA, OSS or PulseAudio.
    – strugee
    Sep 5, 2013 at 19:55
  • 3
    Instead of adding "closed" to your title, you should just answer your own question and leave it
    – jordanm
    Sep 5, 2013 at 19:55

6 Answers 6

28

A one-liner to parse amixer's output for volume in a status bar:

awk -F"[][]" '/dB/ { print $2 }' <(amixer sget Master)

Edit: As of November 2020, the updated amixer for Arch Linux is 1.2.4 which has no 'dB' in the output. So, the command should replaced by:

awk -F"[][]" '/Left:/ { print $2 }' <(amixer sget Master)
7
  • 1
    what does [][] mean? May 24, 2016 at 14:44
  • 4
    @approximatenumber It sets the field separator as either ] or [.
    – jasonwryan
    May 24, 2016 at 18:38
  • 1
    Cool. I didn't know you could have a regex for the F
    – mihai
    Mar 15, 2017 at 17:33
  • 1
    How would you store this command in a variable ?
    – mike23
    Jan 16, 2018 at 21:18
  • 2
    @mike23 vol=$(awk '/%/ {gsub(/[\[\]]/,""); print $4}' <(amixer sget Master))
    – jasonwryan
    Jan 16, 2018 at 21:20
18

You can use amixer to do this.

Examples

$ amixer get Master
Simple mixer control 'Master',0
  Capabilities: pvolume pswitch pswitch-joined penum
  Playback channels: Front Left - Front Right
  Limits: Playback 0 - 65536
  Mono:
  Front Left: Playback 65536 [100%] [off]
  Front Right: Playback 65536 [100%] [off]

You can also change it and mute it like so:

set volume 75%

$ amixer set Master 75%
Simple mixer control 'Master',0
  Capabilities: pvolume pswitch pswitch-joined penum
  Playback channels: Front Left - Front Right
  Limits: Playback 0 - 65536
  Mono:
  Front Left: Playback 49152 [75%] [on]
  Front Right: Playback 49152 [75%] [on]

mute/unmute

$ amixer set Master toggle
Simple mixer control 'Master',0
  Capabilities: pvolume pswitch pswitch-joined penum
  Playback channels: Front Left - Front Right
  Limits: Playback 0 - 65536
  Mono:
  Front Left: Playback 65536 [100%] [on]
  Front Right: Playback 65536 [100%] [on]

You can quiet the output if you don't want to see any of it with the --quiet switch.

$ amixer --quiet set Master 75%
$ 
13

Right

amixer sget Master | grep 'Right:' | awk -F'[][]' '{ print $2 }'
85%

Left

amixer sget Master | grep 'Left:' | awk -F'[][]' '{ print $2 }'
85%

Sound server

If you are not using pulseaudio as default you can specify to amixer what server to use with -D pulse

amixer -D pulse sget Master | grep 'Left:' | awk -F'[][]' '{ print $2 }'
85%
1
  • This doesn't work for me... Master for some reason doesn't have "Left" and "Right" despite other channels such as "Speaker" having it.
    – Michael
    May 3, 2019 at 20:17
1

Based off some of the answers already here, but managed to get avoided using both awk and grep in the same command (because that would be bloat).

amixer -D pulse get Master | awk -F 'Left:|[][]' 'BEGIN {RS=""}{ print $3 }'

Explanation:

amixer -D pulse get Master ...

Pretty self-explanatory; just lists stuff about our Master control (-D pulse because I'm using pulse). For me, it prints:

  Capabilities: pvolume pswitch pswitch-joined
  Playback channels: Front Left - Front Right
  Limits: Playback 0 - 65536
  Mono:
  Front Left: Playback 52428 [80%] [on]
  Front Right: Playback 52428 [80%] [on]

... awk -F 'Left:|[][]' ...

Uses regex to define field separator, which can be Left: or either ][.

... { print $3 }'

Now we print out the 3rd column. Works out that since we separate on Left: as well, that the value of $3 for the right speaker will be blank

... 'BEGIN {RS=""}...

Now we're printing only 80% plus a bunch of newlines. For the script I was writing, I didn't want these, so I removed most of them with {RS=""}, and then got rid of a final one at the start by adding in the BEGIN

0

One Solution i have is with using echo(could not find it anywhere so i would love to know if this is not the best way to do),

echo "${$(echo "${$(amixer get Master | grep Left:)#*\[}")%%\]*}"

i just let Echo delete both the beginning till the first '[' and from the end till the last ']'.

0

Here's what works for me. YMMV.

$ amixer get Master | egrep -o '[0-9]{1,3}%'
51%
$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .