Bash string comparasion does not work as expected [duplicate] - bash

This question already has answers here:
Why should there be spaces around '[' and ']' in Bash?
(5 answers)
Closed 4 months ago.
I use this bash code to test whether two strings are equal, but the result is not as what I exptect. I have used "" to wrap two strings and used [[]] rather than [] in if condition, but still failed. Where did I do wrong? Thanks in advance.
#!/bin/bash
touch a.txt b.txt
date -r a.txt +%y-%m-%d > b.txt
A="$(cat b.txt)"
B="$(date -r a.txt +%y-%m-%d)"
if [["$A" == "$B"]]
then
echo "equal"
else
echo "not equal"
fi
Error is listed below.
➜ ~ chmod a+x test.sh
➜ ~ ./test.sh
./test.sh: line 6: [[22-10-13: command not found
not equal

You need to put a space between [[ and "$A" and between "$B" and ]].
This is because in bash, [, ], [[ and ]] are commands:
$ type [
[ is a builtin
Weird right?

Related

`echo` is stripping newlines in Bash script [duplicate]

This question already has answers here:
I just assigned a variable, but echo $variable shows something else
(7 answers)
When should I double-quote a parameter expansion? [duplicate]
(1 answer)
Closed 5 months ago.
If I have a file containing newlines, the below script will output the file as is, with newlines:
#!/bin/bash
FOO=$(cat filename.yaml)
echo "$FOO"
but
#!/bin/bash
FOO=$(cat filename.yaml)
FOO=$(echo $FOO)
echo "$FOO"
outputs the file all on one line. How come?
I do not recommend storing the contents of entire files in a single variable. In my experience that can have unpredictable results.
/usr/bin/env bash -x
index=$(wc -l filename.yaml | cut -d' ' -f1)
count=1
next () {
[[ "${count}" -lt "${index}" ]] && main
[[ "${count}" -eq "${index}" ]] && exit 0
}
main () {
line=$(sed -n "${count}p" filename.yaml)
echo "var${count}=${line}" >> varfile
count=$(($count+1))
next
}
next
If you source varfile at the start of another script, it will give you every line from that file, in its' own variable.

Comparing two variables in IF condition inside While loop in bash script [duplicate]

This question already has answers here:
Bash comparison operator always true
(1 answer)
How to assign the output of a Bash command to a variable? [duplicate]
(5 answers)
Closed 2 years ago.
i am trying to execute a IF condition inside a while loop, But the IF condition isn't working as variables aren't expanding! kindly guide me through the proper way to compare two variables in IF condition
Note - if you can see the error log - DATE was expanding thou! problem with mdate
DATE=`date +"%Y-%m-%d"`
cat path/temp_b | while read file
do
echo 'phase2'
mtime=$(stat -c '%y' $Src_Dir/$file)
echo $mtime
mdate= echo $mtime | cut -d ' ' -f1
echo $mdate
echo $DATE
if ["$mdate"=="$DATE"]; then
"$file" > path/tempc
else
echo 'hi'
fi
done
**Error log -
phase2
2020-05-07 05:22:28.000000000 -0400
2020-05-07
2020-07-21
./test1.ksh: line 37: [==2020-07-21]: command not found
hi**
Change your if statement like:
if [ "$mdate" == "$DATE" ]; then
Explanation: if in bash needs to have square brackets, operator, and operand to be space-separated.

wildcard expansion in bash function [duplicate]

This question already has answers here:
Assign results of globbing to a variable in Bash
(4 answers)
Closed 7 years ago.
Please, don't take this the wrong way, but before someone answers and tells me I should use an array, I'm looking for the reason why the following code doesn't work, not 'how to do it correctly'.
I've searched the internet for the reason for this.
Given in bash:
function fn1 {
file=$HOME/$1*.cfg
echo $file
}
touch $HOME/abc-def.cfg
fn1 abc
returns /home/user/abc*.cfg
Why doesn't the * expand to give /home/user/abc-def.cfg?
A workaround:
file=$HOME/$(ls -1 $HOME|grep $1)
is not elegant.
Background: I know there will be only one file that begins 'abc', but the rest of the filename can vary, I don't care about that, just the initial identifier (abc in the case above).
Lastly, great forum, use it a lot, but this is the first time I didn't find an answer, so my first posting - be kind :-)
Works for me.
$ function fn1 {
> file=$HOME/$1*.cfg
> echo $file
> }
$
$ touch $HOME/abc-def.cfg
$ fn1 abc
/home/jackman/abc-def.cfg
However, if I disable filename expansion, I see your results:
$ set -f
$ fn1 abc
/home/jackman/abc*.cfg
Have you done set -f beforehand? If you want to account for that in your function:
function fn1 {
local filename_expansion_disabled
[[ $- == *f* ]]; filename_expansion_disabled=$?
local file=$HOME/"$1"*.cfg
[[ $filename_expansion_disabled -eq 0 ]] && set +f
echo $file
[[ $filename_expansion_disabled -eq 0 ]] && set -f || true
}
Then
$ set +f
$ fn1 abc
/home/jackman/abc-def.cfg
$ set -f
$ fn1 abc
/home/jackman/abc-def.cfg
Running the function in a subshell has the same effect, and is simpler at the expense of an insignificant performance penalty:
fn1() (
file=$HOME/"$1"*.cfg
set +f
echo $file
)

Bash - Get first 3 letters of filename [duplicate]

This question already has answers here:
Extract substring in Bash
(26 answers)
Closed 8 years ago.
I have a little bash script and have $file and $file2 variable. This is file and I want to get first 3 letters of this file name. And I want to compare them:
I tried:
curfile=$(basename $file)
curfilefirst3=${curfile:0:3}
curfile2=$(basename $file2)
curfile2first3=${curfile2:0:3}
if ((curfilefirst3 == curfile2first3 )); then
....
But I think have problems, how can I fix?
Thank you.
You're missing $ for the strings in the comparison and you'll need to wrap each string with " and the entire expression with []:
file="this.txt"
file2="that.txt"
curfile=$(basename $file)
curfilefirst3=${curfile:0:3}
curfile2=$(basename $file2)
curfile2first3=${curfile2:0:3}
echo $curfile2first3
echo $curfilefirst3
if [ "$curfile2first3" == "$curfilefirst3" ]
then
echo "same!"
else
echo "different!"
fi
It might be a good idea to read up on bash conditionals
Substring Extraction
${string:position} Extracts substring from $string at $position.
However, if should use [ and not ( as in:
if [ $curfilefirst3 == $curfile2first3 ]; then
The corrected version:
#!/bin/bash
file=abcdef
file2=abc123456
curfile=$(basename $file)
curfilefirst3=${curfile:0:3}
curfile2=$(basename $file2)
curfile2first3=${curfile2:0:3}
echo $curfilefirst3
echo $curfile2first3
if [ $curfilefirst3 = $curfile2first3 ]; then
echo same
else
echo different
fi
It prints same
So, works

Error in shell script if condition [duplicate]

This question already has answers here:
Bash if statement syntax error [duplicate]
(3 answers)
Closed 9 years ago.
I didnt understand what he error here as iam new to shell scripting. Please help me
./bpr: line 8: syntax error near unexpected token `then'
./bpr: line 8: ` if[$(grep -o BPR $file | wc -l) == 1]; then '
You need to add spaces between your [ ], try this:
if [ $(grep -o BPR $file | wc -l) == 1 ]; then
You need a space around your condition:
if [ $(grep -o BPR $file | wc -l) == 1 ]; then
^ ^
1) If you are using bash, you can use the built-in [[ ..]] instead of test ([ ...]) command.
2) You can also avoid wc by using -c option of grep.
if [[ $(grep -c -o BPR $file) == 1 ]]; then
Aside from your syntax errors, you don't need wc either if you don't care that there may be multiple occurrances of BPR in the file:
if grep -o BPR "$file"; then
A couple of things:
You need spaces around [ and ].
You probably don't want to use [ and ].
The if statement runs the command you give it. If the command returns a zero, the then portion of the if statement is executed. If the command returns a non-zero, the else portion (if it exists) is executed.
Try this:
$ if ls some.file.name.that.does.not.exist
> then
> echo "Hey, the file exists!"
> else
> echo "Nope. File isn't there"
> fi
You'll get an output:
ls: some.file.name.that.does.not.exist: No such file or directory
Nope. File isn't there
That first statement, of course is the output of your ls command. The second one is the output from the if statement. The ls ran, but couldn't access that file (it doesn't exist) and returned e 1. That caused the else clause to execute.
Try this:
$ touch foo
$ if ls foo
> echo "Hey, the file exists!"
> else
> echo "Nope. File isn't there"
> fi
You'll get an output:
foo
Hey, the file exists!
Again the first line is your output from ls. Since the file exists, and is statable, ls returned a 0. This caused the if clause to execute, printing the second line.
What if I want to test whether or not a file exists?
You can use the test command:
$ if test -e foo
> then
> echo "Hey, the file exists!"
> else
> echo "Nope. File isn't there"
> fi
If the file foo exists, the test command returns a 0. That means the echo "Hey, the file exists!" will execute. If the file doesn't exist, test will return a 1, and the else clause will execute.
Now do this:
$ ls -il /bin/test /bin/[
10958 -rwxr-xr-x 2 root wheel 18576 May 28 22:27 /bin/[
10958 -rwxr-xr-x 2 root wheel 18576 May 28 22:27 /bin/test
That first number is the inode. If two matching files have the same inode, they are hard linked to each other. The [... ] are merely another name for the test command. The [ is an actual command. That's why you need spaces around it. You also see that if tests whether or not a command succeeds, and doesn't really do boolean checking (the exception is if you use double square brackets like [[ and ]] instead of [ and ]. These are built into the shell and not as builtin commands.)
What you probably want to do is:
if grep -q "BPR" "$file"
then
echo "'BPR' is in '$file'"
fi
The -q flag tells grep to shut its yap. The grep command will return a 0 if the pattern you give it is in the file, and a non-zero (exact value doesn't matter -- as long as it isn't 0) if it can't.
Note I don't need [ ... ] because I am using the output of the grep command to see if I should execute the if clause of that statement.
if you only need to know if the string matches without showing the actual match use
if grep -q 'anystring' file ; then

Resources