0

I've just found this command:

upower -e

that displays a list of files that can be used with upower -i to display plugged device status.

So my first try was using:

upower -e | xargs upower -i

but it doesn't work. So I've tried:

$ upower -e | xargs echo
/org/freedesktop/UPower/devices/line_power_AC /org/freedesktop/UPower/devices/battery_BAT0 /org/freedesktop/UPower/devices/line_power_ucsi_source_psy_USBC000o001 /org/freedesktop/UPower/devices/DisplayDevice

and it display all files in single line. So I've used:

$ upower -e | xargs -0 echo
/org/freedesktop/UPower/devices/line_power_AC
/org/freedesktop/UPower/devices/battery_BAT0
/org/freedesktop/UPower/devices/line_power_ucsi_source_psy_USBC000o001
/org/freedesktop/UPower/devices/DisplayDevice

it works but displays one empty line, but this doesn't work:

$ upower -e | xargs -0 upower -i
failed to set path: Object path invalid: /org/freedesktop/UPower/devices/line_power_AC
/org/freedesktop/UPower/devices/battery_BAT0
/org/freedesktop/UPower/devices/line_power_ucsi_source_psy_USBC000o001
/org/freedesktop/UPower/devices/DisplayDevice

Why upower -e | xargs upower -i doesn't work? I'm using Bash on Fedora.

Is there something I'm missing here?

EDIT:

This seems to work:

upower -e | xargs -I {} upower -i "{}"

But I'm wondering: why a quote is needed if the filename doesn't have spaces?

jcubic
  • 9,932
  • Possibly upower -i can only handle a single object path at a time? Try upower -e | xargs -L 1 upower -i – steeldriver Apr 10 '22 at 18:36
  • @steeldriver got an answer on Twitter from the original author that posted this command, and it shows xargs -I {} works, but the files don't have spaces, then why this is needed? – jcubic Apr 10 '22 at 18:38
  • -I isn't really needed, but it implies -L1 as a side effect - that's what's really making the difference here I think – steeldriver Apr 10 '22 at 18:40
  • ... because the LHS should be upower -e presumably? upower -i needs an input path – steeldriver Apr 10 '22 at 18:45
  • @steeldriver Yes it was my mistake that I've just noticed, I've deleted that from my edit and comment. – jcubic Apr 10 '22 at 18:46
  • @steeldriver Thanks for your help. if you want to add this as an answer you can. I'm not sure how much people look at answers and comments on Unix SE. – jcubic Apr 10 '22 at 18:47
  • OK thanks - done – steeldriver Apr 10 '22 at 19:00

1 Answers1

2

upower -e produces a newline-separated list of object paths.

When you used upower -e | xargs upower -i, the xargs command tokenized that on whitespace and passed all the paths to a single invocation of upower -i, which it was unable to handle.

You then tried upower -e | xargs echo, and noted that the output consisted of a single line - that's down to echo though, and does not tell you how the output of upower -e was delimited.

Next you tried upower -e | xargs -0 echo, which (since the output of upower -e is not null delimited) passed a single multi-line argument to echo, which happily printed it. Similarly upower -e | xargs -0 upower -i passed a single multi-line path to upower -i, which unsurprisingly barfed.

Finally you discovered upower -e | xargs -I {} upower -i "{}". Since -I implies -L, this passed each line of the upower -e output to a separate invocation of upower -i. You could have achieved the same with

upower -e | xargs -L upower -i

Whitespace within the paths isn't a factor here, but if it was, you should tell xargs not only to read a single line per invocation, but also to tokenize it on newlines only:

upower -e | xargs -d '\n' -L upower -i

or equivalently

upower -e | xargs -d '\n' -n 1 upower -i

Quoting the replacement text {} probably isn't necessary either (regardless of whether the text itself contains whitespace) - see Quoting curly braces in the shell and the linked duplicate discussing the same issue in the context of find -exec

steeldriver
  • 81,074
  • Didn't know about xargs -d '\n', it will be useful, most of the time I process lines with xargs. – jcubic Apr 10 '22 at 19:19