Check if WC Command output is greather than in BASH - linux

I need to check if wc command output is greather than a variable. Here's my code:
if test wc -w $i -gt $num
then
echo "too great"
fi
If the current file $i contains more words than the $num variable i print "too great". I already tried all but can't get the script working.

You need to take the output of the wc command and use it as an argument to test:
if test "$( wc -w < "$i" )" -gt "$num"
See "Command Substitution" in man bash.
If you don't use redirection <, wc also outputs the file name, which would break the comparison.

Related

Stop grep message from posting

I am working on a script that take 1 string argument and a file. I want it so that if a file is put in that doesn't exist, then it will display the "filename cannot be read" message.
That part does work however it also displays a "grep: grep.txt: No such file or directory" message. Is there any way to stop the grep message from posting and ending the script if the first if statement is true?
#! /bin/sh
if [ ! -f "$2" ]
then
echo "$0" cannot be read 1>&2
fi
if [ $# -eq 2 ]
then
grep "$1" $2
else
echo there is more or less than 2 arguments 1>&2
fi
Exit the script with a non-zero exit code to indicate failure and stop it from continuing on to the grep.
if [ ! -f "$2" ]
then
echo "$0" cannot be read 1>&2
exit 1
fi
You can add /dev/null in grep command it will suppress the error part.
grep "$1" $2 2>/dev/null
The > operator redirects the output usually to a file but it can be to a device. You can also use >> to append.
2> file redirects stderr to file
/dev/null is the null device it takes any input you want and throws it away. It can be used to suppress any output.
You could redirect all errors from grep, for example:
grep "$1" $2 2>/dev/null
(the 2> means redirect standard error, as opposed to standard output with > or 1>).
That introduces a race condition, however: if the file disappears while your script as running, it might still exist when you check that it exists, but be gone by the time grep runs.
You could handle that by checking the exit status...
grep "$1" $2 2>/dev/null
if [[ $? -gt 1 ]]; then
echo "grep failed unexpectedly" >&2
fi
IMHO, in this example it would be better to just let grep print the error.

Place grep result into variable

I have a problem with bash script. I have a list of files in specific location. I have to take only a date from it and compare it with another date.
for i in *.gz; do
echo $i | grep -Eo '[[:digit:]]{4}-[[:digit:]]{2}-[[:digit:]]{2}'
done
The above is greping date from filenames correctly but only when I use echo. In another cases I have errors. I have tried:
tmp=$(echo $i | grep -Eo '[[:digit:]]{4}-[[:digit:]]{2}-[[:digit:]]{2}')
Also not working. Any suggestions? I would be grateful for small help!
I wouldn't use grep at all here; use bash's built-in regular-expression handling.
for i in *.gz; do
[[ $i =~ [[:digit:]]{4}-[[:digit:]]{2}-[[:digit:]]{2} ]]
echo "${BASH_REMATCH[0]}"
done
One way around it, could be using stat command
for i in *.gz; do
tmp=$(stat "$i" | awk '/Modify/ { print $2}' )
done
or if you want an array
declare -a tmp
tmp+=$(
for i in *.gz; do
stat "$i" | awk '/Modify/ { print $2}'
done
)
The advantage is, that it is independent of the file names
edit:
I cannot comment on others answwers yet. So this is how you compare date
sixago=$(date --date='-6 month' +%s)
tmp=$(date --date="$tmp" +%s)
if [ "$tmp" -gt "$sixago" ];then
...
fi

Bash scripting wanting to find a size of a directory and if size is greater than x then do a task

I have put the following together with a couple of other articles but it does not seem to be working. What I am trying to do eventually do is for it to check the directory size and then if the directory has new content above a certain total size it will then let me know.
#!/bin/bash
file=private/videos/tv
minimumsize=2
actualsize=$(du -m "$file" | cut -f 1)
if [ $actualsize -ge $minimumsize ]; then
echo "nothing here to see"
else
echo "time to sync"
fi
this is the output:
./sync.sh: line 5: [: too many arguments
time to sync
I am new to bash scripting so thank you in advance.
The error:
[: too many arguments
seems to indicate that either $actualsize or $minimumsize is expanding to more than one argument.
Change your script as follows:
#!/bin/bash
set -x # Add this line.
file=private/videos/tv
minimumsize=2
actualsize=$(du -m "$file" | cut -f 1)
echo "[$actualsize] [$minimumsize]" # Add this line.
if [ $actualsize -ge $minimumsize ]; then
echo "nothing here to see"
else
echo "time to sync"
fi
The set -x will echo commands before attempting to execute them, something which assists greatly with debugging.
The echo "[$actualsize] [$minimumsize]" will assist in trying to establish whether these variables are badly formatted or not, before the attempted comparison.
If you do that, you'll no doubt find that some arguments will result in a lot of output from the du -m command since it descends into subdirectories and gives you multiple lines of output.
If you want a single line of output for all the subdirectories aggregated, you have to use the -s flag as well:
actualsize=$(du -ms "$file" | cut -f 1)
If instead you don't want any of the subdirectories taken into account, you can take a slightly different approach, limiting the depth to one and tallying up all the sizes:
actualsize=$(find . -maxdepth 1 -type f -print0 | xargs -0 ls -al | awk '{s += $6} END {print int(s/1024/1024)}')

Too many arguments in for

In both for statements, I am getting the following error:
./count_files.sh: line 21: [: too many arguments
./count_files.sh: line 16: [: too many arguments.
Can anyone help me ?
#!/bin/bash
files=($(find /usr/src/linux-headers-3.13.0-34/include/ -type f -name '[aeiou][a-z0-9]*.h'))
count=0
headerfiles=($(find /usr/src/linux-headers-3.13.0-34/include/ -type f -name '[_a-zA-Z0-9]*.h' | grep -v "/linux/"))
for file in "${files[#]}"
do
if ! [ grep -Fxq "linux/err.h" $file ];
then
localcount=0
for header in "${headerfiles[#]}"
do
if [ grep -Fxq $header $file ];
then
localcount=$((localcount+1))
if [ $localcount -eq 3 ];
then
count=$(($count+1))
break
fi
fi
done
localcount=0
fi
done
echo $count
One of the problem lines is:
if ! [ grep -Fxq "linux/err.h" $file ];
The semicolon at the end is unnecessary unless the then is on the same line; it is, however, harmless.
It looks as though you want to execute the grep command and check whether it produces any output. However, you've simply provided the test (aka [) command with four string arguments (plus the closing ] for 5 in total), the second of which is not one of the options recognized by test.
You might have meant to use this:
if ! [ -n "$(grep -Fxq "linux/err.h" "$file")" ]
(unless you meant -z instead of -n; the negations are confusing me). But if you're interested in whether grep found anything, you can simply test the exit status of grep:
if grep -Fxq "linux/err.h" "$file"
Hmmm...the -q is 'quiet' mode; so in fact the string test won't work since grep produces no output. You want the direct test of the exit status, possibly preceded by the ! logical not operator.
You shouldn't use square brackets around the grep.
In shell scripts square brackets are not used for grouping, [ is a command in its own right (an alias for test), and it is the [ command that is complaining that you've given it too many arguments.
Just make the call without brackets
if ! grep ....
Change the fors to whiles with reads:
...
echo "${files}" | while read file ; do
...
echo "${headerfiles}" | while read header ; do
...
done
...
done
...

Bash Script : Unwanted Output

I have this simple bash script:
I run ns simulator on each file passed in argument where last argument is some text string to search for.
#!/bin/bash
nsloc="/home/ashish/ns-allinone-2.35/ns-2.35/ns"
temp="temp12345ashish.temp"
j=1
for file in "$#"
do
if [ $j -lt $# ]
then
let j=$j+1
`$nsloc $file > $temp 2>&1`
if grep -l ${BASH_ARGV[0]} $temp
then
echo "$file Successful"
fi
fi
done
I expected:
file1.tcl Successful
I am getting:
temp12345ashish.temp
file1.tcl Successful
When i run the simulator command myself on the terminal i do not get the file name to which output is directed.
I am not getting from where this first line of output is getting printed.
Please explain it.
Thanks in advance.
See man grep, and see specifically the explanation of the -l option.
In your script (above), you are using -l, so grep is telling you (as instructed) the filename where the match occurred.
If you don't want to see the filename, don't use -l, or use -q with it also. Eg:
grep -ql ${BASH_ARGV[0]} $temp
Just silence the grep:
if grep -l ${BASH_ARGV[0]} $temp &> /dev/null

Resources