Shell script for searching a string pattern in file name - shell

Hi i want to write a script that will go to a directory with many files and search a filename e.g. test_HTTP_abc.txt for this and search for HTTP string pattern, if it contains this string then set a variable equal to something:
something like:
var1=0
search for 06
if it contains 06 then
var1=1
else
var1=0
end if
but in unix script . Thanks

Probably the simplest thing is:
if test "${filename#*HTTP}" = "$filename"; then
# the variable does not contain the string `HTTP`
var=0
else
var=1
fi
Some shells allow regex matches in [[ comparisons, but it's not necessary to introduce that sort of non-portable code into your script.

Like this?
var=0
if fgrep -q 06 /path/to/dir/*HTTP*
then
var=1
fi
fgrep will return 0 ("truth") if there is a match in one of the files, and non-true otherwise (including the case of no matching input files).
If you want a list of matching files, try fgrep -l.

Well, I'm not going to write the script for you, you have to learn :)
Its easy if you break it down into smaller tasks;
The ls command is for looking at a directorie's contents. You can also use the find command to be a bit more intuitive, like find /some/folder -name "*string*"
To sift through the output of a command. You could store the output of a command to a variable or at using pipes.
You can search this output with something like awk (link), grep (link) an so on.
Setting variables is easy also in bash; http://tldp.org/HOWTO/Bash-Prog-Intro-HOWTO-5.html
foundit=1
Why don't you have a go at trying to solve this puzzle first rather than someone telling you :D Show us where you get stuck in the puzzle.

Related

Bash for loop testing two boolean expressions

Below is a simple bash program. It takes file types as command line arguments and it queries the current directory and prints the files of the type specified.
I would like to be able to query two different file types and therefore need two boolean expressions to represent this.
Below is my code for querying just one file type
#!/bin/bash
for x in $(ls *$1); do
echo $x;
done
Now what I would like to be able to do is (in pseudocode)
command line args fileName .sh .c
for x in (current directory files of *.sh) OR (in current directory files of *.c) do
print .sh files
print.c files
done
I've tried using || and I get syntax errors I can not find any evidence of being able to use || for two expressions in for loop.
I've tried using two nested for loops but they do not work and yield errors.
Is there any way I can accomplish this using the same for loop system.
Thank you.
Sounds like you want something like:
for extension in "$#"; do
printf 'Files ending in %s:\n' "$extension"
printf '%s\n' *"$extension"
done
Loop through all arguments passed to the script and print all files ending in each extension + a newline character.
Note that printf is a much more useful tool than echo, as it allows you to control the format of each thing is prints.
ls doesn't do anything useful either here; it is the shell which expands the * to the list of files matching the pattern.

Split a namefile in shell

I'm here to know how to split a file name that was found by a ls comand :D. Let me explain better...
I have a variable
images=$( ls | grep .img )
And then i want to split the result of the search, because i just want the name before the .img, so a nice idea is use IFS.
IFS=. read -r disk <<< $image
Pretty nice, but when a do an echo with the $disk variable, what i see is a ".img" just that, i want to recover where is before that dot.
Thank you all, and sorry for any mistake :)
Use the stream editor sed! Example:
echo "myImage.jpg" | sed 's/.jpg//'
That s means "substitute", and you substitute the part between the first two slashes for the part between the second and third slash, so in the example, ".jpg" for the empty string.
That's all!
Since you mention using <<<, I'll assume you are using a shell that supports arrays (specifically, bash. Other shells--notably zsh--may use different syntax for what I am about to describe).
images=( *.img ) # No need to parse ls, which is generally a bad idea
Assuming there is only one matching file, you can then use
disk=${images%.img}
to strip .img from the file name and save the remaining portion in disk. If there could be multiple matches, you can apply the extension stripping to each element of the array and store the result in a second array.
disks=( "${images[#]%.img}" )
basename is what you want.
From the man page:
basename - strip directory and suffix from filenames
EXAMPLES
basename /usr/bin/sort
Output "sort".
basename include/stdio.h .h
Output "stdio".

Is it possible to concatenate variables on fly and make string subsitution on the result?

String substitution with single variable:
FOO=fooo
echo ${FOO%o}
The output for this is: foo.
How to do this with concatenation? Something like this:
FOO=fooo
echo ${FOO$FOO%o}
The output for this is (my wish): fooofoo.
If this is possible at all.
In other words, I would like to concatenate several strings (using variables) and then apply string substitution to entire string (concatenation of all variables), not just single variable.
As far as I know, there isn't a way to do that as a single bash operation. You'll need to perform the concatenation into a variable first follow by the required parameter substitution/expansion.
FOO=foooo
TMP=$FOO$FOO # concatenation
echo "${TMP%o}" # parameter substitution on concatenated string
If you feel that the extra var assignment makes it less readable, you could opt for the less efficient (but more recognisable) approach of piping the output to another command that performs a similar operation, e.g.:
[me#home]$ FOO="fooo"
[me#home]$ TMP=$FOO$FOO; echo ${TMP%o} # bash only, with temp var
fooofoo
[me#home]]$ echo $FOO$FOO | sed 's/o$//' # pipe to an equivalent operation
fooofoo
In addition, depending on what your end goal is there may be cleaner ways to accomplish it.
For example, a common situation when concatenation followed by trimming is required would be for path manipulation, i.e.:
[me#home]$ APP_ROOT=/opt/myapp
[me#home]$ APP_PATH=/config/hello.cfg
[me#home]$ FULL_PATH=$APP_ROOT$APP_PATH
[me#home]$ echo ${FULL_PATH%/hello.cfg}
/opt/myapp/config
In which case the "cleaner" approach would be:
[me#home]$ dirname $APP_ROOT$APP_PATH
/opt/myapp/config
If you can share what you've trying to achieve perhaps there's a more elegant solution to be had.
See below for two possible answers, depending on exactly what you are looking for:
Answer #1:
FOO=fooo
echo "${FOO}${FOO%o}"
Output:
fooofoo
Answer #2:
FOO=fooo
echo "${FOO%o}${FOO%o}"
Output:
foofoo
Answer #3:
FOO=fooo
CONCAT="$FOO$FOO"
echo "${CONCAT%ofooo}"
foo

bash script get files in subfolders which contains a special line

I need your help with a short bash script. I have a folder, which contains about 150,000(!) xml-files. I need a script which extracts all those files, which contain a specified line. The script should be work as fast as possible, because the script have to be used very often.
My first approach was the following, using grep:
for f in temp/*
do
if grep "^.*the line which should be equal.*$" "$f"
then
echo "use this file"
else
echo "this file does not contain the line"
fi
done
This approach works, but it takes too much time. Does somebody know an faster approach? If another scripting language is a better choice, it is also ok.
Best regards,
Michael
You can use grep without any bash handlers.
-l, --files-with-matches
Suppress normal output; instead print the name of each input file from which output would normally have been printed. The scanning will stop on the first match. (-l is
specified by POSIX.)
So, try this:
grep "the line which should be equal" --files-with-matches temp/*

Shell Script : If a string is present in a file

I am a newbie to shell scriptng and I want to check if 3 strings("hello","who","when " etc) are present in a file.
I find many ways when I google out awk,cat ,grep etc ,What can be the best way and how Can I do it.
I just need to know if the strings are present or not .
Your question is a little incomplete:
do you want to find strings or words? So when the word Othello appears, does that count as hello?
in your question there is whitespace behind the when. Is that intentional?
do you want to know whether all three words are in the file, or is one of the words enough?
The general solution is to use grep or egrep to search for text in a file. The exact command line depends on the answers to the above questions.
to search for words (Othello doesn't count as hello) you need to pass the -w option to grep.
I'm assuming thhat the whitespace was a mistake.
When you need all the words, you can do egrep -wo 'hello|who|when' | sort -u. The egrep command finds all instances of the given words, and prints them out one per line. At that point, you will have many duplicates. Therefore the sort -u command sorts them and only keeps the unique lines (that's what the -u means). In a complete program, I would do it as follows:
filename="story.txt"
words=$(egrep -wo 'hello|who|when' "$filename" | sort -u)
n=$(echo "$words" | wc -l)
if [ $n = 3 ]; then
echo "found all words in the file"
else
echo "didn't find all words, only \""$words"\"."
fi
There's a lot more that I could tell you about this little piece of code, and why I wrote it exactly like that, but for a beginner, it's already enough to understand.
But just in case that you need a simple solution and the file is small anyway, so performance is not critical, you can do this:
filename="story.txt"
if egrep -wl 'hello' "$filename" 1>/dev/null; then
if egrep -wl 'when' "$filename" 1>/dev/null; then
if egrep -wl 'who' "$filename" 1>/dev/null; then
echo "found all three words"
fi
fi
fi
[Update:]
This second code snippet also checks whether the given file contains all three words. Each of the if clauses checks for one of the words. The option -l (lowercase ell) to egrep makes it potentially faster, but you probably don't need that option at all.
Normally egrep prints all lines that match the given expressions (your three words in this case). Since we don't need that output, we redirect it using the arrow operator > to a special file called /dev/null. Whatever you write into that file is discarded.
The if statement takes another command as its argument, and if that command returns successfully, the then branch is taken. The nice thing about the egrep command is that it returns successfully iff the given search expression is contained in the file, so these two things perfectly fit together.
For further reading you should try the reference documentation from the Open Group website: http://www.google.com/search?q=opengroup+grep

Resources