i wrote a shell script as you can see followed. The script reads all line which in .dat file and writes screen matching words according to specified parameter but if/else block doesn’t properly.Both block if and else fired same time.
sh file
#!/bin/bash
p="*.dat"
k="$1"
for f in $p
do
if [ "$k" == "$f" ]; then
echo "$f present"
else
echo "not found $k"
fi
cat $f
done
dat file
lorem ipsum loremium dolor sit amet ipso
terminal
$ ./loc.sh lor
result
not found lor lorem ipsum loremium dolor sit amet ipso
Advertisement
Answer
The original code didn’t ever look inside of a file until after running the comparison — it merely compared the name of each .dat file to the target, and allowed only exact matches (not substrings).
Consider instead:
while read -r line; do
if [[ $line = *"$1"* ]]; then
echo "$1 present in $line"
else
echo "$1 not found in $line"
fi
done < <(cat *.dat)
- Using
cat *.datcombines all the files into a single stream. Enclosing this in<(cat *.dat)generates a filename which can read from to yield that stream; using< <(cat *.dat)redirects stdin from this file (within the scope of thewhileloop for which this redirection takes place). - Using
while readprocesses an input stream line-by-line (see BashFAQ #1). - Using a test of
[[ $line = *"$1"* ]]allows the target (contents of$1) to be found inside a line, instead of only matching when$1matches the entire line as a whole. You can also have this effect with[[ $line =~ "$1" ]]. Note that the quotes are mandatory for correct operation in either of these cases. Using a
forloop to iterate over lines is extremely poor practice; see Don’t Read Lines With For. If you want to use aforloop, use it to iterate over files instead:for f in *.dat; do # handle case where no files exist [[ -e "$f" ]] || continue # read each given file while read -r line; do if [[ $line = *"$1"* ]]; then echo "$1 present in $line in file $f" else echo "$1 not present in $line in file $f" fi done <"$f" done