Linux bash if no arguments

Check existence of input argument in a Bash shell script

You did not tell us how you invoked this script. most likely, the first parameter was not an integral number.

How do I check the input argument1 first to see if it exists? : Do you mean «how do I check whether the argument 1 is non-empty?» or do you mean «how do I check whether the number of arguments is greater than zero?». Please clarify this in your question.

12 Answers 12

if [ $# -eq 0 ] then echo "No arguments supplied" fi 

The $# variable will tell you the number of input arguments the script was passed.

Or you can check if an argument is an empty string or not like:

if [ -z "$1" ] then echo "No argument supplied" fi 

The -z switch will test if the expansion of «$1» is a null string or not. If it is a null string then the body is executed.

I like to do it this way, in terse syntax and still POSIX acceptable. [ -z «$1» ] && echo «No argument supplied» I prefer one-liners, as they are easier for me; and it’s also faster to check exit value, compared to using if

You probably want to add an exit 1 at the end of your echos inside the if block when the argument is required for the script to function. Obvious, but worth noting for completeness.

It is possible, though rarely useful, for the first argument to be initialized but empty; programname «» secondarg third . The $# check unambiguously checks the number of arguments.

For a noob, especially someone who comes from a non-scripting background, it is also important to mention some peculiarities about these things. You could have also mentioned that we need a space after the opening and the closing brace. Otherwise things do not work. I am myself a scripting noob (I come from C background) and found it the hard way. It was only when I decided to copy the entire thing «as is» that things worked for me. It was then I realized I had to leave a space after the opening brace and before the closing one.

Источник

Bash, no-arguments warning, and case decisions

I am learning bash. I would like to do a simple script that, when not arguments given, shows some message. And when I give numers as argument,s depending on the value, it does one thing or another. I would also like to know suggestions for the best online manuals for beginners in bash Thanks

5 Answers 5

if [[ $# -eq 0 ]] ; then echo 'some message' exit 0 fi case "$1" in 1) echo 'you gave 1' ;; *) echo 'you gave something else' ;; esac 

The Advanced Bash-Scripting Guide is pretty good. In spite of its name, it does treat the basics.

RE: «exit 0». I don’t know if exiting the script was what he had in mind. But yes, that’s an excellent guide.

I interpreted «and» as «otherwise», assuming that the message would be some help text. But I’m sure Werner is able to figure out what that line does and whether he wants it 🙂

Читайте также:  Чем клонировать диск linux

thanks, of course! and last thing, how can i turn off error messages ib the script, so they are not shown to the shell?

You mean the errors coming out of a particular program you’re calling? You can put > /dev/null and/or 2> /dev/null after that to send its standard output and/or standard error streams into oblivion.

If you consider a missing argument something bad (like the script then cannot perform successfully), return something different than 0 ( exit 1 ). There are further conventions about return/exit codes, that you can find online quickly, but the important point is that it should not be 0, which indicates success.

If only interested in bailing if a particular argument is missing, Parameter Substitution is great:

#!/bin/bash # usage-message.sh : $ # Script exits here if command-line parameter absent, #+ with following error message. # usage-message.sh: 1: Usage: usage-message.sh ARGUMENT 

Example

 if [ -z "$*" ]; then echo "No args"; fi 

Result

Details

-z is the unary operator for length of string is zero. $* is all arguments. The quotes are for safety and encapsulating multiple arguments if present.

Use man bash and search (/ key) for «unary» for more operators like this.

A (minor) problem with this is that it doesn’t distinguish between passing no arguments and passing an empty string as argument. That may be important in some contexts. Using [ $# -eq 0 ] one can handle both cases properly.

Old but I have reason to rework the answer now thanks to some previous confusion:

if [[ $1 == "" ]] #Where "$1" is the positional argument you want to validate then echo "something" exit 0 fi 

This will echo «Something» if there is no positional argument $1. It does not validate that $1 contains specific information however.

$# is explicitly the integer count of the number of arguments; it will either be «0», and you will echo «something» even though there are no arguments, or it will be some positive number, and you will echo «something» correctly. But the check itself will never do anything, regardless of the input or lack of input you use — it will always report that $# contains a value. So this is completely wrong and will never work as claimed.

Are you completely positive of that? I have several scripts that work as intended using this exact format. Upon reading your response I even retested both for the match and lack thereof. $# will not contain a value if not specified, if there is no positional argument to match what ever # is in your scenario. It makes no sense why bash would assume a value in a positional argument that isn’t there.

Try echo $# as the contents of a script /tmp/test.sh, then run it under /bin/bash as well as /bin/sh (or /bin/dash and whatever other shell implementations you have available. /tmp/test.sh will echo «0» to the console, as will /bin/dash /tmp/test.sh . On the other hand, /tmp/test.sh foo will echo «1», and /tmp/test.sh first second will echo «2».

As per man bash , in the section «Special Parameters», «The shell treats several parameters specially. These parameters may only be referenced; assignment to them is not allowed.», and «# Expands to the number of positional parameters in decimal.» It is likewise mandated by POSIX as described in pubs.opengroup.org/onlinepubs/9699919799/utilities/…

Читайте также:  Linux отмонтировать файловую систему

Sorry looks like there was a miscommunication! I meant # as a place holder for the specific positional argument (i.e, $2 if you meant the second argument) not literal $#. After reviewing your above you are absolutely correct, a literal $# will always resolve to the number of arguments. Apologies for the confusion.

Источник

Check if no command line arguments and STDIN is empty

How to check, in a Bash script, that no command line arguments or STDIN was provided ? I mean if I run:

#> ./myscript.sh . Show message "No data provided. " and exit 
#> ./myscript.sh filename.txt . Read from filename.txt 

4 Answers 4

Does this fit your requirements ?

#!/bin/sh if test -n "$1"; then echo "Read from $1"; elif test ! -t 0; then echo "Read from stdin" else echo "No data provided. " fi 

The major tricks are as follow:

  • Detecting that you have an argument is done through the test -n $1 which is checking if a first argument exists.
  • Then, checking if stdin is not open on the terminal (because it is piped to a file) is done with test ! -t 0 (check if the file descriptor zero (aka stdin ) is not open).
  • And, finally, everything else fall in the last case ( No data provided. ).

Yes, sorry for my erroneous edit. I misread your code and thought for a while that you were using read with a timeout.

Would it work with stdin from a pipe though? Hmmm. probably. But it would fail if stdin had been explicitly closed. The -t test is true if the fd is open and associated with a terminal. If its false, either its closed or not associated with a terminal.

@Kusalananda: You are totally right! If stdin has been closed for some other reason, it will wrongly deduce that it reads from a file given on stdin . But, I do not see how to do better than that. If you can come with a better solution, I would be delighted to see it!

@perror I don’t think it matters too much as read would return (with a «bad filediscriptor» error) immediately, and that could be handled as a data error, i.e. the data was supposed to come from standard input, but there was something wrong with it.

I searched far and wide to no avail, and finally managed to put this together through much trial and error. It has worked flawlessly for me in numerous use-cases ever since.

#!/bin/bash ### LayinPipe.sh ## Recreate "$" as "$"; appending piped input. ## Offers usable positional parameters regardless of where the input came from. ## ## You could choose to create the array with "$" instead following ## any piped arguments by simply swapping the order ## of the following two 'if' statements. # First, check for normal positional parameters. if [[ $ ]]; then while read line; do Args[$]="$" done < <(printf '%s\n' "$") fi # Then, check for piped input. if [[ ! -t 0 ]]; then while read line; do Args[$]="$" done < <(cat -) fi # Behold the glory. for ((a=0;a<$;a++)); do echo "$: $" done 
  • Example: (knowing full well that using output of 'ls' as input is discouraged in order to show the flexibility of this solution.)
$ ls : TestFile.txt 'Filename with spaces' $ ls -1 | LayinPipe.sh "$(ls -1)" > 0: Filename with spaces > 1: TestFile.txt > 2: Filename with spaces > 3: TestFile.txt $ LayinPipe.sh "$(ls -1)" > 0: Filename with spaces > 1: TestFile.txt $ ls -1 | LayinPipe.sh > 0: Filename with spaces > 1: TestFile.txt 

Источник

Читайте также:  Linux help info man

How to read stdin when no arguments are passed?

Script doesn't work when I want to use standard input when there are no arguments (files) passed. Is there any way how to use stdin instead of a file in this code? I tried this:

if [ ! -n $1 ] # check if argument exists then $1=$(

5 Answers 5

For a general case of wanting to read a value from stdin when a parameter is missing, this will work.

$ echo param | script.sh $ script.sh param 

set -- $ <@:-$(if you want read all arguments from the positionals, stdin otherwise. (Like how grep behaves.)

Just substitute bash's specially interpreted /dev/stdin as the filename:

VAR=$1 while read blah; do . done < "$" 

(Note that bash will actually use that special file /dev/stdin if built for an OS that offers it, but since bash 2.04 will work around that file's absence on systems that do not support it.)

pilcrow's answer provides an elegant solution; this is an explanation of why the OP's approach didn't work.

The main problem with the OP's approach was the attempt to assign to positional parameter $1 with $1=. , which won't work.

The LHS is expanded by the shell to the value of $1 , and the result is interpreted as the name of the variable to assign to - clearly, not the intent.

The only way to assign to $1 in bash is via the set builtin. The caveat is that set invariably sets all positional parameters, so you have to include the other ones as well, if any.

set -- "$" "$" # "$" expands to all remaining parameters 

(If you expect only at most 1 argument, set -- "$" will do.)

The above also corrects a secondary problem with the OP's approach: the attempt to store the contents rather than the filename of stdin in $1 , since < is used.

$ is an application of bash parameter expansion that says: return the value of $1 , unless $1 is undefined (no argument was passed) or its value is the empty string ( "" or '' was passed). The variation $ (no : ) would only return /dev/stdin if $1 is undefined (if it contains any value, even the empty string, it would be returned).

If we put it all together:

# Default to filename '/dev/stdin' (stdin), if none was specified. set -- "$" "$" while read -r line; do . # find the longest line done < "$1" 

But, of course, the much simpler approach would be to use $ as the filename directly:

while read -r line; do . # find the longest line done < "$" 

or, via an intermediate variable:

filename=$ while read -r line; do . # find the longest line done < "$filename" 

Источник

Оцените статью
Adblock
detector