shell script -o operation is not working - linux

DISPLAY_HEADER=1
if [ "$1" != "test" -o "$1" != "test2" ]
then
if [ $DISPLAY_HEADER == 1 ]; then
DISPLAY_HEADER=0
echo "sdasa "
echo $1
fi
fi
its display sdasa and -o is not working ?
what is wrong ?

you can use case/esac
case "$1" in
test|test2)
# do something
*)
# set display data
;;
esac

Related

Trying to implement CASE in my shell script

I'm trying to add options to my little safe delete script. For example, I can do ./sdell -s 100 and it will delete files with size above 100 kbs. Anyway, I'm having problems with my safe guard function.
#!/bin/bash
#Purpose = Safe delete
#Created on 20-03-2018
#Version 0.8
#jesus,i'm dumb
#START
##Constants##
dir="/home/cunha/LIXO"
#check to see if the imputs are a files#
for input in "$#"; do
if ! [ -e "$input" ]; then
echo "Input is NOT a file!"
exit 1
fi
done
###main###
case $1 in
-r) echo "test option -r"
;;
*) if [[ -f "$dir/$fwe.tar.bz2" ]]; then
echo "File already exists."
if [[ "$file" -nt "$2" ]]; then
echo "Removing older file." && rm "$dir"/"$fwe.tar.bz2" && tar -czPf "$fwe.tar.bz2" "$(pwd)" && mv "$fwe.tar.bz2" "$d$
fi
else
echo "Ziping it and moving." && tar -czPf "$fwe.tar.bz2" "$(pwd)" && mv "$fwe.tar.bz2" "$dir"
fi
done
;;
esac
The problem is when I call ./sdell -r file1.txt, it says that the input is not a file.
Here is the script without the case, 100% working before having options.
#!/bin/bash
#Purpose = Safe delete
#Created on 20-03-2018
#Version .7
#START
##Constants##
dir="/home/cunha/LIXO"
#check to see if the imputs are a files#
for input in "$#"; do
if ! [ -e "$input" ]; then
echo "Input is NOT a file!"
exit 0
fi
done
###main###
##Cycle FOR so the script accepts multiple file inputs##
for file in "$#"; do
fwe="${file%.*}"
#IF the input file already exist in LIXO#
if [[ -f "$dir/$fwe.tar.bz2" ]]; then
echo "File already exists."
#IF the input file is newer than the file thats already in LIXO#
if [[ "$file" -nt "$2" ]]; then
echo "Removing older file." && rm "$dir"/"$fwe.tar.bz2" && tar -czPf "$fwe.tar.bz2" "$(pwd)" && mv "$fwe.tar.bz2" "$d$
fi
else
echo "Ziping it and moving." && tar -czPf "$fwe.tar.bz2" "$(pwd)" && mv "$fwe.tar.bz2" "$dir"
fi
done
The message you are seeing is unrelated to the case..esac, construct, it is printed by this section:
for input in "$#"; do
if ! [ -e "$input" ]; then
echo "Input is NOT a file!"
exit 1
fi
done
which expands all command-line parameters ($#), including the "-r", and exits the script because "-r" is not a file. The case..esac is never reached. You can run your script with
bash -x file.sh -r test
so that you can see exactly which lines are being executed.
The snippet below probably does what you want, processing all arguments sequentially:
#!/bin/bash
while [ ! -z $1 ]; do
case $1 in
-r) echo "option R"
;;
-f) echo "option F"
;;
*) if [ -f $1 ]; then echo "$1 is a file." ; fi
;;
esac
shift
done
Consider checking if -r has been passed before trying other options and use shift if it was:
#!/usr/bin/env sh
dir="/home/cunha/LIXO"
case $1 in
-r) echo "test option -r"
shift
;;
esac
#check to see if the imputs are a files#
for input in "$#"; do
echo current input: "$input"
if ! [ -e "$input" ]; then
echo "Input $input is NOT a file!"
exit 1
fi
done
if [[ -f "$dir/$fwe.tar.bz2" ]]; then
echo "File already exists."
if [[ "$file" -nt "$2" ]]; then
echo "Removing older file..."
# add stuff
fi
else
echo "Ziping it and moving."
# add stuff
fi

IF statement multiple and or conditions

I am using if statement with multiple condition in bash.
How can I reduce the following line syntax. So that it looks good from design point of you.
if [ "$1" != "-l" ] && [ "$1" != "-a" ] && [ "$1" != "-h" ] && [ "$1" != "" ] && [ "$1" = "-d" ] || [ "$1" = "-mv" ] || [ "$1" = "-dv" ] || [ "$1" = "-mr" ] || [ "$1" = "-dr" ];
Thanks
Use pattern matching.
if [[ $1 && $1 != -[lah] && $1 == -#(d|mv|dv|mr|dr) ]]; then
#(...) is an example of an extended pattern, which should be recognized by default inside [[ ... ]] in recent versions of bash. If you version is not so recent, add shopt -s extglob to the beginning of your script.
In fact, you can drop the $1 && $1 != -[lah] because its truth would be implied by the truth of $1 == -#(...).
if [[ $1 == -#(d|mv|dv|mr|dr) ]]; then
You could also just use a POSIX-compliant case statement:
case $1 of
-d|-mv|-dv|-mr|-dr) echo good option ;;
*) echo bad option ;;
esac
You can create 2 arrays for matching and non matching values and check if element $1 matches any element in the array or not like below.
nonmatch_array=( "-l" "-a" "-h" "" )
match_array=( "-d" "-mv" "-dv" "-mr" "-dr" )
if [ `echo ${match_array[#]} | grep "$1"` ] || ! [ `echo ${nonmatch_array[#]} | grep "$1"` ] ; then
echo "is in array"
else
echo "is not in array"
fi
Hope it should work for you.
First try to limit the length of the code on 1 line.
if [ [ "$1" != "-l" ]
&& [ "$1" != "-a" ]
&& [ "$1" != "-h" ]
&& [ -n "$1" ]
&& ( [ "$1" = "-d" ]
|| [ "$1" = "-mv" ]
|| [ "$1" = "-dv" ]
|| [ "$1" = "-mr" ]
|| [ "$1" = "-dr" ] ) ];
I added braces, to make clear what you mean with the or's.
Now you can combine all matches with a regular expression:
if [[ ! ("$a" =~ ^-(l|a|h|d|)$)
&& "$a" =~ ^-(mv|dv|mr|dr)$ ]]; then
echo "Yes $a matches"
fi
but reconsider what you are testing. The test will only be true when it matches -mv/-dv/-mr/-dr, so you do not need to test for the options lah.
if [[ "$a" =~ ^-(d|mv|dv|mr|dr)$ ]]; then
echo "Yes $a matches"
fi
You can use a variable for extracting the options:
options="d|mv|dv|mr|dr"
if [[ "$a" =~ ^-(${options})$ ]]; then
echo "Yes $a matches"
fi
Everytime the code is becoming hard to read (and also for long code or repeating statements), you should consider using a function.
The next function is short, but hard to read:
options="d|mv|dv|mr|dr"
function checkoption1 {
[[ "$a" =~ ^-(${options})$ ]]
}
checkoption1 "$a" &&
echo "Yes $a matches"
I would choose for a slightly more verbose function. I will include your original tests for lah for showing the possibilities.
# checkoption return 0 for match,
# returns 1 for forbidden option
# returns 2 for undefined option
function checkoption2 {
case "$1" in
-d|-mv|-dv|-mr|-dr) return 0 ;;
-l|-a|-h|"") return 1;;
*) return 2;;
esac
}
checkoption2 "$a" &&
echo "Yes $a matches"
You should make some testruns before accepting your code.
I have made some tests with a small loop (now all answers together)
function checkoption1 {
[[ "$a" =~ ^-(${options})$ ]]
}
# checkoption return 0 for match,
# returns 1 for forbidden option
# returns 2 for undefined option
function checkoption2 {
case "$1" in
-d|-mv|-dv|-mr|-dr) return 0 ;;
-l|-a|-h|"") return 1;;
*) return 2;;
esac
}
for a in -mv mv -mvx -ms -mr -dr; do
if [[ ! ("$a" =~ ^-(l|a|h|)$)
&& "$a" =~ ^-(d|mv|dv|mr|dr)$ ]]; then
echo "Yes $a matches"
fi
if [[ "$a" =~ ^-(d|mv|dv|mr|dr)$ ]]; then
echo "Yes $a matches"
fi
options="d|mv|dv|mr|dr"
if [[ "$a" =~ ^-(${options})$ ]]; then
echo "Yes $a matches"
fi
checkoption1 "$a" &&
echo "Yes $a matches"
checkoption2 "$a" &&
echo "Yes $a matches 2"
done

Options on bash script (completely new to this)

So I'm beginning making bash scripts. I can do basic stuff, but that's it.
I want to make something so when I type in:
./myprogram -t
It will do "echo true"
And if I type in:
./myprogram -f
It will do "echo false"
Thanks in advance
The positional parameters are available through the variables $1 $2 etc.
There are many ways to implement the contition. You could use an if statement:
#!/bin/bash
if [ "$1" = -t ]
then
echo true
elif [ "$1" = -f ]
then
echo false
fi
A case statement:
#!/bin/bash
case "$1" in
-t) echo true ;;
-f) echo false ;;
esac
Or a short-circuit:
#!/bin/bash
[ "$1" = -t ] && echo true
[ "$1" = -f ] && echo false
For more complex cases consider using the getopt or the getopts libraries.
The word for what you are calling an "option" is typically referred to as an argument in programming. You should read more about how to handle arguments in bash by reading everything at http://tldp.org/LDP/abs/html/othertypesv.html . To answer your direct question the script might look like this:
#!/bin/bash
if [[ $# -eq 0 ]]; then
echo 'No Arguments'
exit 0
fi
if [ $1 = "-f" ]; then
echo false
elif [ $1 = "-t" ]; then
echo true
fi

nitrogen --restore to scale background

so I found a script online and found it pretty suitable to my needs. basically it edits the file nitrogen places it's saved wallpaper in to another picture, so I can change the wallpaper periodically with a cron job.
#!/bin/bash
WPDIR="$HOME/Wallpapers"
random=true
apply=true
wpfile=""
function usage {
if [ $1 -eq 1 ]; then
stream=2
exitcode=255
else
stream=1
exitcode=0
fi
echo "Usage: $(basename $0) [-n|--noapply] [-h|--help] [wallpaper_location]" >&$stream
echo "If wallpaper location is not given a random wallpaper from $WPDIR will be chosen" >&$stream
exit $exitcode
}
# handle arguments
while [ $# -gt 0 ]; do
if [ "$1" = "--help" -o "$1" == "-h" ]; then
usage 0
elif [ "$1" = "--noapply" -o "$1" = "-n" ]; then
apply=false
else
if ! $random; then
usage 1
elif [ ! -f "$1" ]; then
echo "file '$1' not found" >&2
exit 1
fi
random=false
{ cd $(dirname "$1"); dir=$(pwd); }
wpfile="$dir/$(basename "$1")"
fi
shift
done
if $random; then
wpfile=$(ls "$WPDIR"/*.jpg | sort -R | head -n 1)
echo "chose $wpfile" >&2
fi
cat >$HOME/.config/nitrogen/bg-saved.cfg <<EOF
[:0.0]
file=$wpfile
mode=4
bgcolor=# 0 0 0
EOF
if $apply; then
nitrogen --restore
fi
my problem is the scaling of the pictures. I can't set it to auto-fill this way.
I'm bad, I should feel bad. When writing to >$HOME/.config/nitrogen/bg-saved.cfg , the mode is set. this mode is literally the mode nitrogen provides. Try a bit around with nitrogen and look what mode is set in the file. zoomed-fill = 5, for my example.

Bash - compare if argument "is one of"

I want to test if the first argument is one of: "ABC" or "DEF" or "GHI".
And if it's not - print usage and exit.
if [[ "$1" =~ ^(ABC|DEF|GHI)$ ]]; then
echo "usage"
exit
fi
This case runs in sh and bash:
case "$1" in
'ABC' | 'DEF' | 'GHI') ;;
*) echo "usage"
exit;;
esac
You could just use a normal if statement with string comparison:
if [ "$1" != "ABC" -a "$1" != "DEF" -a "$1" != "GHI" ]; then
echo "Usage: $0 ABC|DEF|GHI"
exit 0
fi
Or:
if [ "$1" = "ABC" -o "$1" = "DEF" -o "$1" = "GHI" ]; then
# Do something.
else
echo "Usage: $0 ABC|DEF|GHI"
exit 0
fi

Resources