Bash - function with optional arguments and missing logic

I am trying to make a simple function for the useradd command and quickly improve my poor shell programming skills.

useradd -m -g [initial_group] -G [additional_groups] -s [login_shell] [username] 

Right now I'm somewhat unsure of how to work with optional arguments. After some Googling, and I think it might be related to this, you just need to play around with the code.

One thing I'm not sure about is the logic, and I'm curious how you guys are going to write this. I am sure it will be better than I could hack together.


This is how I try to configure my function arguments, for the login shell and initial group I would have common default values.

 arg1 - userName, required arg2 - loginShell, optional (default: /bin/bash) arg3 - initGroup, optional (default: users) arg4 - otherGroups, optional (default: none) 

This is some kind of lame pseudo code about how I am going to structure this.

 function addUser( userName, loginShell, initGroup, otherGroups){ // Not how I would go about this but you should get the point string bashCmd = "useradd -m -g "; // Adding the initial user group if(initGroup == null){ bashCmd += "users"; } else { bashCmd += initGrop; } // Adding any additional groups if(otherGropus != null){ bashCmd += " -G " + otherGroups; } if(loginShell == null){ bashCmd += " -s /bin/bash " + userName; } else { bashCmd += " -s " + loginShell + " " + userName; } } 

These are the links I'm going to make

http://tldp.org/HOWTO/Bash-Prog-Intro-HOWTO-8.html

Passing Bash Function Parameters

How to write a Bash script that accepts optional input arguments?

Using functions inside a document

+4
source share
3 answers

@rob mayoff's answer is the easiest way to accomplish this, but I thought I'd stumble on turning your pseudo-code into real shell syntax to point out some standard errors for people used to β€œreal” programming languages. First, three main points:

  • Different shells have different capabilities, so use bash (i.e. run your script with #!/bin/bash or run it with the bash command) if you need bash extensions. If you use only the basic functions and syntax of the Bourne shell, start it with the sh command ( #!/bin/sh or sh ). If you do not know, suppose you need bash.
  • When creating a command for subsequent execution, there are all kinds of legible oddities that you may encounter (see BashFAQ # 050: I try to command in a variable, but complex cases always fail! ). The best way, as a rule, is to create it as an array, not a string. "Of course, arrays are a bash extension, not a basic shell function ...
  • In shell syntax, spaces matter. For example, in the command if [ -n "$2" ]; then if [ -n "$2" ]; then space after the semicolon is optional (and there may also be a space before the semicolon), but all other spaces are required (without them, the command will do something completely different). In addition, the task cannot have spaces around the equal sign, or (again) it will do something completely different.

With that in mind, here I take on the function:

 addUser() { # The function keyword is optional and nonstandard, just leave it off. Also, # shell functions don't declare their arguments, they just parse them later # as $1, $2, etc bashCmd=(useradd -m) # you don't have to declare variable types, just assign to them -- the # parentheses make this an array. Also, you don't need semicolons at the # end of a line (only use them if you're putting another command on the # same line). Also, you don't need quotes around literal strings, because # everything is a string by default. The only reason you need quotes is to # prevent/limit unwanted parsing of various shell metacharacters and such. # Adding the initial user group if [ -z "$3" ]; then # [ is actually a command (a synonym for test), so it has some ... parsing # oddities. The -z operator checks whether a string is empty (zero-length). # The double-quotes around the string to be tested are required in this case, # since otherwise if it zero-length it'll simply vanish. Actually, you # should almost always have variables in double-quotes to prevent accidental # extra parsing. # BTW, since this is a bash script, we could use [[ ]] instead, which has # somewhat cleaner syntax, but I'm demonstrating the difficult case here. bashCmd+=(-g users) else bashCmd+=(-g "$3") # Here, double-quotes here are not required, but a good idea in case # the third argument happens to contain any shell metacharacters -- # double-quotes prevent them from being interpreted here. -g doesn't # have any shell metacharacters, so putting quotes around it is not # necessary (but wouldn't be harmful either). fi # Adding any additional groups if [ -n "$4" ]; then bashCmd+=(-G "$4") fi # Set the login shell if [ -z "$2" ]; then bashCmd+=(-s /bin/bash "$1") else bashCmd+=(-s "$2" "$1") fi # Finally, run the command "${bashCmd[@]}" # This is the standard idiom for expanding an array, treating each element # as a shell word. } 
+6
source

You may find the extension ${parameter:+word} useful. From the Bash Reference Guide:

If the parameter is null or unset, nothing is replaced, otherwise the word is replaced.

So:

 function addUser { useradd -m ${2:+-s "$2"} ${3:+-g "$3"} ${4:+-G "$4"} "$1" } 

Note that this function handles quoting correctly if any of the arguments contains funny characters (for example, spaces, dollar signs, or other shell metacharacters). If you try to compose a command line, it is much more difficult to bring it into line. It does not matter if it is only for your personal, short-term use, and you know that input is safe. But it’s better not to leave the script or function lying around if it is designed to run with root privileges and does not handle its input very carefully.

+12
source

google for abs to get lots of sophisticated patterns

 function addUser{ userName=$1; loginShell=$2; initGroup=$3 otherGroups=$4; args=(-m -g); // Adding the initial user group if [[ $initGroup == '' ];then args+=(users); else args+=("$initGrop"); fi; # Adding any additional groups if [[ $otherGroups != '' ]];then args+=(-G "$otherGroups"); fi; if [[ $loginShell == '' ]];then args+=(-s /bin/bash "$userName"); else args+=(-s "$loginShell" "$userName"); fi; useradd "${args[@]}" } 

the code is not verified, but I hope I don’t miss anything

0
source

Source: https://habr.com/ru/post/1443781/


All Articles