Issue While Validating Bash Script

Issue while validating BASH Script

An earlier line:

if [ "$1" -ne "dev" ] || [ "$1" -ne "production" ]; then

will always be true. That should probably be

if [ "$1" != "dev" -a "$1" != "production" ]; then

@Andrea is also correct that the &&'s don't make sense

You would probably be better off using a case statement:

case "$1" in
dev)
echo "found dev"
;;
production)
echo "found production"
;;
*)
echo "not dev or prod, or not present"
;;
esac

Validating parameters to a Bash script

#!/bin/sh
die () {
echo >&2 "$@"
exit 1
}

[ "$#" -eq 1 ] || die "1 argument required, $# provided"
echo $1 | grep -E -q '^[0-9]+$' || die "Numeric argument required, $1 provided"

while read dir
do
[ -d "$dir" ] || die "Directory $dir does not exist"
rm -rf "$dir"
done <<EOF
~/myfolder1/$1/anotherfolder
~/myfolder2/$1/yetanotherfolder
~/myfolder3/$1/thisisafolder
EOF

edit: I missed the part about checking if the directories exist at first, so I added that in, completing the script. Also, have addressed issues raised in comments; fixed the regular expression, switched from == to eq.

This should be a portable, POSIX compliant script as far as I can tell; it doesn't use any bashisms, which is actually important because /bin/sh on Ubuntu is actually dash these days, not bash.

Validating bash script argument by flag name and value

[ -z mypassword ] will always evaluate to false, because the word mypassword has a length greater than zero. You could test with, for instance, [[ -z $mypassword ]].

Also, the term ${p:} does not make sense. Perhaps you meant ${p:=} ?

UPDATE:

One more note: The way you are invoking your script would not work, even after those fixed, becaues mypassword will always be empty. For your script to work, p must be an environment variable holding the password. You would have to call your script (assuming it is in your working directory) like this:

# To run it as sh-script (POSIX shell)
p=THIS_IS_MY_PASSWORD sh myscript.sh

# To run it as bash-script, if the script is executable
p=THIS_IS_MY_PASSWORD ./myscript.sh

# To run it as bash-script, if the script is not executable
p=THIS_IS_MY_PASSWORD bash myscript.sh

How do I syntax check a Bash script without running it?

bash -n scriptname

Perhaps an obvious caveat: this validates syntax but won't check if your bash script tries to execute a command that isn't in your path, like ech hello instead of echo hello.

Strange behavior using read for validate string (bash script)

Use find better

for filename in $(anything) is always an antipattern -- it splits values on characters in IFS, and then expands each result as a glob. To make find emit completely unambiguous strings, use -print0:

while IFS= read -r -d '' filename; do
[ -e "$filename" ] || continue
echo "$filename"
done < <(find "$SRC_DIR" -name '*.proto' -print0)


Don't change IFS unnecessarily

Change your code to make the assignment to IFS be on the same line as the read, which will make IFS only be modified for that one command.

That is to say, instead of:

IFS=/
read -a SUBSTR <<<"$t"

...you should write:

IFS=/ read -a SUBSTR <<<"$t"

Validating file existence in a Makefile for executing a script

you have to make this a huge, single bash command; make executes each line separately in the shell and variables are not available in later steps. To improve readability/maintainability, I would replace the test -f ... && xxx statements here by if blocks.

E.g.

execute-%-s3-sync: ...
MANIFEST="$(if $(filter $*,large-files),large-files,$(call get-source-s3-bucket,$*)).gz" && \
ADDITION="target/migrations/$(TARGET_DATA_EXPORT_KEY)/diff/$(SOURCE_DATA_EXPORT_KEY)/additions/$$MANIFEST" && \
DELETION="target/migrations/$(TARGET_DATA_EXPORT_KEY)/diff/$(SOURCE_DATA_EXPORT_KEY)/deletions/$$MANIFEST" && \
if test -f "$$ADDITION"; then \
...
fi && \
if test -f "$$DELETION"; then \
...

Regarding failing, you have to express things in a positive manner. E.g.

  • BAD:

    test -f $FILE && do_something    ## --> will fail when $FILE does not exists
  • GOOD:

    ! test -f $FILE || do_something  ## --> fails only, when do_something fails
  • GOOD:

    if test -f $FILE; then
    do_something
    fi

Validation using While and IF

How about modifying the function to return the validated score. Then you can enclose the looping until the valid number is given within the function.

Then the code will look like:

#!/bin/bash

function validate_marks() {
local subject=$1
local score
while true; do
read -p "Enter ${subject}:" score
if [[ "$score" =~ ^[0-9]+$ ]] && [[ "$score" -ge 0 ]] && [[ "$score" -le 100 ]]; then
echo "$score"
return
else
echo "** Enter numbers between 0-100 **" >&2
fi
done
}

echo "Enter Marks for each subject:"

ENG=$(validate_marks "English Marks")
MATHS=$(validate_marks "Maths Marks")
SCI=$(validate_marks "Science Marks")
HIST=$(validate_marks "History Marks")
EMAIL=$(validate_marks "your Email id")
  • while true creates an infinite loop to keep on asking for an input until the if condition is met.
  • The "$score" =~ ^[0-9]+$ portion checks if the user input is a number just to avoid an internal error.
  • The output of the bash function is transmitted to the caller via stdout with echo or something like that.
  • Then the message within the function should be sent to stderr by >&2.

Hope this helps.

Validate input in bash script

Since you are reading input twice, I would use a function to check it. This way you do not repeate code.

This checks whether input contains just digits and at least one. Otherwise, it keeps asking for the input:

myread () {
while : # infinite loop
do
read value
[[ $value =~ ^[0-9]+$ ]] && echo "$value" && return #return value if good input
done
}

echo -n "Enter width: "
width=$(myread) #call to the funcion and store in $width

echo -n "Enter height: "
height=$(myread) #call to the funcion and store in $height

echo "Area of rectangle $(echo "$height*$width" | bc) sqcm"

Catch return code from composer validate in bash script

You are trusting too much the reliability of composer exit codes.

The command

composer validate --no-check-all

is returning zero and it's correct, because the command has no real problems in its execution. Consider capturing the output in a variable and reading it.

#!/bin/bash

OUTPUT=$(composer validate --no-check-all)

if [[ "$OUTPUT" == *"is valid"* ]]; then
echo "composer.json is valid (or whatever you want to do here)"
fi

Secure Input Validation in Bash/Shell Script

You could do something like this:

#!/bin/bash

set -e

while read path; do
result=`realpath -m -- "$path"`
if [ "$result" != "$path" ] && [ "$result/" != "$path" ] ; then
echo "Rejected: $path"
else
last_char_index=$((${#path}-1))
last_char=${path:$last_char_index:1}
if [ "$last_char" == "/" ]; then
echo "New directory: $path"
mkdir -- "$path"
else
echo "New file: $path"
touch -- "$path"
fi
fi
done

exit 0

I use realpath to catch relative paths, then always use user input between double quotes to avoid commands injection (if any is possible).
I guess there are better ways of doing but at the moment that's all I can think of.

Edit: as advised in the comments, I added -- to ensure the file/directory names are safely given to touch, mkdir and realpath.



Related Topics



Leave a reply



Submit