0

I have created a new user. My current user obviously has the following rights:

$ groups
max adm cdrom sudo dip plugdev lpadmin lxd sambashare

Where max is the name of the current user account.

I tried paramer expansion but the output of ${groups} is empty, so I just piped groups to xargs

$ groups | xargs -I _ sudo usermod -aG _ new_user_name

I get the error message that there is no folder max adm cdrom sudo dip plugdev lpadmin lxd sambashare because obviously the output of groups is not splitted by whitespace.

But as I said ${groups} is empty, so there is nothing I could pipe to xargs.

Second try:

my_arr=(adm cdrom sudo dip plugdev lpadmin lxd sambashare)

$ echo ${my_arr[@]} | xargs -I _ usermod -aG _ new_user_name

The arguments of the array don't get splitted even though I don't put the parameter expansion in double quotes.

xargs treats the piped arguments still as one big string adm cdrom sudo dip plugdev lpadmin lxd sambashare

What's the right solution?

tripleee
  • 175,061
  • 34
  • 275
  • 318
von spotz
  • 875
  • 7
  • 17
  • 2
    You're using `/bin/sh`??? Arrays are a Bash feature, not POSIX `sh`. – iBug May 18 '21 at 11:35
  • 1
    To somewhat expand on the previous comment, you need to use `#!/bin/bash` instead of `#!/bin/sh` (or not use an array, and figure out a different approach). See also [Difference between `sh` and `bash`](https://stackoverflow.com/questions/5725296/difference-between-sh-and-bash) – tripleee May 18 '21 at 11:46
  • I rolled back your latest edit, since it distracts from the main question and is covered by a common FAQ. – tripleee May 18 '21 at 12:01
  • Okay, my fault. I am very sorry for my error. The script of iBug worked with `#!/bin/bash`. Thanks for your efforts. I am just a beginner with working with the shell. Thanks for pointing me to `"Difference between sh and bash"` I will read and learn. – von spotz May 18 '21 at 12:04

3 Answers3

1

usermod adds one or more users to one group at a time, so you'll have to use a loop:

for g in "${my_arr[@]}"; do
  usermod -aG "$g" new_user_name
done

Note that xargs by default uses as many arguments as possible in one invocation of the supplied command, so if you go with xargs, limit the number of arguments consumed to one at a time (-n 1):

echo "${my_arr[@]}" | xargs -n 1 -I _ usermod -aG _ new_user_name
iBug
  • 35,554
  • 7
  • 89
  • 134
  • So I would have to put a `\n` or something at the end of each array string? Btw: Why isn't producing ${groups} any output ? Thanks – von spotz May 18 '21 at 11:16
  • 1
    @vonspotz No you don't add newlines manually. Using a loop is about as good as you can go. BTW: Use `$(groups)` to capture output of commands, not expanding variables. – iBug May 18 '21 at 11:17
  • I have edited my original post. Please take a look. Thanks! – von spotz May 18 '21 at 11:34
  • I'm sorry but still the same error message `usermod: the group »max adm cdrom sudo dip plugdev lpadmin lxd sambashare« doesn't exist` – von spotz May 18 '21 at 11:46
  • @vonspotz Please edit your question to include the exact command you ran so we can take a look. – iBug May 18 '21 at 11:48
  • Notice that `"${my_arr[@]}"` is a Bash feature which is not compatible with `sh`. – tripleee May 18 '21 at 12:02
  • The followup question https://stackoverflow.com/questions/67589593/bash-copying-files-with-xargs-why-do-i-get-this-returned-as-the-last-argument/67589819#67589819 solves the remaining problem. – tripleee May 20 '21 at 11:00
1

The crucial problem is that you need to tell xargs to read one argument at a time.

Less crucially, you probably don't want to include max in the input to usermod.

groups |
# Trim away first token (max)
sed 's/^[^ ]* //' |
# Pass to xargs with -n 1
xargs -n 1 -I _ sudo usermod -aG _ new_user_name

On Linux you may need to add --delimiter ' ' to the xargs command line.

tripleee
  • 175,061
  • 34
  • 275
  • 318
  • Yes, right, group `max` shouldn't be included, but I thought I would stifle the problem of adding to user group `max` until the rest would at least be working. Also I can remove one group manually, but I don't see why I shouldn't use bash to add the set of groups in general. – von spotz May 18 '21 at 11:51
  • I'm not saying don't use Bash. I'm saying don't use Bash features if you are _actually_ using `sh`. But this answer does not try to use arrays or other Bash features so it should work fine with either. – tripleee May 18 '21 at 11:52
  • I'm sorry but still the same error message as below :( It just doesn't split the arguments as it actually should. What else would the purpose of xargs be. – von spotz May 18 '21 at 11:54
  • 1
    On Linux you may need to add `--delimiter ' '` and perhaps `-r`. – tripleee May 18 '21 at 11:58
-2

You can use xargs -i flag. This will split up your string and in your next statement, you can access each token using {}. This will run the sudo command for each of the groups.

So try

groups | xargs -i sudo usermod -aG {} new_user_name

user1717259
  • 2,717
  • 6
  • 30
  • 44