How to suppress this sed in Bash? - bash

#!/bin/bash
set_bash_profile()
{
local bash_profile="$HOME/.profile"
if [[ -w $bash_profile ]]; then
if (grep 'MY_VAR' $bash_profile 2>&1); then
sed -i '/MY_VAR/d' $bash_profile
fi
echo "export MY_VAR=foo" >>$bash_profile
fi
}
set_bash_profile
Here is the first run:
bash-4.1$ ./set_bash.sh
No output --which is great! And cat shows export MY_VAR=foo was appended to the file. But when executing a second time, I want sed to silently edit $bash_profile without outputting the matching string, like it does here:
bash-4.1$ ./set_bash.sh
export MY_VAR=foo

You get the output from grep on grep 'MY_VAR' $bash_profile 2>&1. grep outputs the matched line in your profile:
export MY_VAR=foo
on stdout. The 2>&1 only forwards stderr to stdout. It's good to use -q option with grep. Also the subshell (...) around the grep is not needed. Try this:
#!/bin/bash
set_bash_profile()
{
local bash_profile="$HOME/.profile"
if [ -w $bash_profile ]; then
if grep -q 'MY_VAR' $bash_profile; then
sed -i '/MY_VAR/d' $bash_profile
fi
echo "export MY_VAR=foo" >>$bash_profile
fi
}
set_bash_profile

Related

How to create log file from my bash script

How can I make a log file from my bash script?
I'm leaving the script without the options, all I want to know is how I can register the script being used and make a separate .log file.
Script:
#!/bin/bash
trash=~/TRASH
if [ ! -e $trash ]; then
mkdir $trash
elif [ ! -d $trash ]; then
echo "$0: error: $trash is not a directory"; exit 1
fi
while getopts "hr:t:s:u:" options; do
case $options in
#ALL THE OPTIONS AREN'T HERE FOR THE PURPOSE OF KEEPING IT SHORTER
shift $((OPTIND-1))
while [ $# -gt 0 ]; do
if [ ! -e $1 ]; then
echo "$0: error: tried to delete file that does not exist: $1"
shift
continue
fi
tarname="$1.tar"
tar -cf "$tarname" "$1"
mv "$tarname" $trash
rm -rf "$1"
shift
done
To display stdout and stderr to both the console and the log, and to append to the log, perhaps something like:
#!/bin/bash
(
blah code
) 2>&1 | tee -a file.log
Where:
2>&1 - redirect stderr to stdout
| tee -a file.log - send stdout to console but also 'tee' up a copy to be -appended to file.log
Working example:
$ cat blah
(
echo "hello" # will print to stdout
dirxys # will send message to stderr
) 2>&1 | tee -a blah.log
# both stdout/stderr show up on console:
$ blah
hello
./blah: line 3: dirxys: command not found
# both stdout/stderr also show up in log:
$ cat blah.log
hello
./blah: line 3: dirxys: command not found
One way...
#!/bin/bash
(
blah code
) > file.log
Just call the script and redirect its output:
./script.sh > script.log
late answer
this with parenthesis dont work for sh files of type
wget that ...
wget that ...
wget that ...
Solution:
./script.sh 2>&1 | tee -a file.log

How to run commands off of a pipe

I would like to run commands such as "history" or "!23" off of a pipe.
How might I achieve this?
Why does the following command not work?
echo "history" | xargs eval $1
To answer (2) first:
history and eval are both bash builtins. So xargs cannot run either of them.
xargs does not use $1 arguments. man xargs for the correct syntax.
For (1), it doesn't really make much sense to do what you are attempting because shell history is not likely to be synchronised between invocations, but you could try something like:
{ echo 'history'; echo '!23'; } | bash -i
or:
{ echo 'history'; echo '!23'; } | while read -r cmd; do eval "$cmd"; done
Note that pipelines run inside subshells. Environment changes are not retained:
x=1; echo "x=2" | while read -r cmd; do eval "$cmd"; done; echo "$x"
You can try like this
First redirect the history commands to a file (cut out the line numbers)
history | cut -c 8- > cmd.txt
Now Create this script hcmd.sh(Referred to this Read a file line by line assigning the value to a variable)
#!/bin/bash
while IFS='' read -r line || [[ -n "$line" ]]; do
echo "Text read from file: $line"
$line
done < "cmd.txt"
Run it like this
./hcmd.sh

Grep is not showing results even i used fgrep and -f options

I have used the below content to fetch some values .
But the grep in the code is not showing any results.
#!/bin/bash
file=test.txt
while IFS= read -r cmd;
do
check_address=`grep -c $cmd music.cpp`
if [ $check_address -ge 1 ]; then
echo
else
grep -i -n "$cmd" music.cpp
echo $cmd found
fi
done < "$file"
Note : there are no carriage return in my text file or .sh file.
i checked using
bash -x check.sh
It is just showing
+grep -i -n "$cmd" music.cpp

How to echoing data from WHOIS records with grep (redirecting standard output into a variable)

I have this bash script:
How I can call it the grep's output in the if else statement? If I suppress the output of the grep command with -q, also will work?
#!/usr/bin/env bash
DOMAINS=( '.com' '.biz' )
while read input; do
for (( i=0;i<${#DOMAINS[#]};i++)); do
jwhois --force-lookup --disable-cache --no-redirect -c jwhois.conf "$input${DOMAINS[$i]}" | MATCH="$(grep -oPa '^.*\b(clientTransferProhibited)\b.*$')"
if [ $? -eq 0 ]; then
echo -e "$input${DOMAINS[$i]}\tregistered\t" $(date +%y/%m/%d_%H:%M:%S) "\t" "$MATCH" |& tee --append output/registered.txt
else
echo -e "$input${DOMAINS[$i]}\tavailable\t" $(date +%y/%m/%d_%H:%M:%S) "\t" "$MATCH" |& tee --append output/available.txt
fi
done
done < "$1"
So MATCH="$(grep -oPa '^.*\b(clientTransferProhibited) used by "$MATCH" in the if else statement not outputting anything, but if I just use grep -oPa '^.*\b(clientTransferProhibited), it's printing the line without problem. The reason why I want to use as a variable, because I want to put in specific places in the if else statements.
Actual output:
$ domain1.com available 15/11/16_14:13:05
$ domain1.biz available 15/11/16_14:13:05
$ domain2.com registered 15/11/16_14:13:05
$ domain2.biz registered 15/11/16_14:13:05
Output that I want:
$ domain1.com available 15/11/16_14:13:05
$ domain1.biz available 15/11/16_14:13:05
$ domain2.com registered 15/11/16_14:13:05 Status: clientTransferProhibited http://www.icann.org/epp#clientTransferProhibited
$ domain2.biz registered 15/11/16_14:13:05 Status: clientTransferProhibited http://www.icann.org/epp#clientTransferProhibited
So the result of this line is what you want stored in a variable...
jwhois --force-lookup --disable-cache --no-redirect -c jwhois.conf "$input${DOMAINS[$i]}" | grep -oPa '^.*\b(clientTransferProhibited)\b.*$'
In that case, you want to evaluate that line and set the entire thing to your desired variable. The type of assignment you attempt in the middle of a pipeline will not be valid.
MATCH=$(jwhois --force-lookup --disable-cache --no-redirect -c jwhois.conf "$input${DOMAINS[$i]}" | grep -oPa '^.*\b(clientTransferProhibited)\b.*$')
Those are two different MATCH variables, because pipes execute subshells:
Bash subshell/pipelines - which parts are executing in subshells?
Try it this way instead:
MATCH="$(jwhois --force-lookup --disable-cache --no-redirect -c jwhois.conf "$input${DOMAINS[$i]}" | grep -oPa '^.*\b(clientTransferProhibited)\b.*$')"

Redirect grep output to file

I am not sure as to why that redirection provided in the code does not work. Every time I run the script, the output file is always empty. Does anyone have an idea on that?
Thanks.
#!/bin/sh
LOOK_FOR="DefaultProblem"
FILES=`ls plugins/*source*.jar`
for i in $FILES
do
# echo "Looking in $i ..."
unzip -p $i | grep -i $LOOK_FOR > output #> /dev/null
if [ $? == 0 ]
then
echo ">>>> Found $LOOK_FOR in $i <<<<"
fi
done
You may want to use >> (append) instead of > (overwrite) for redirection as:
unzip -p $i | grep -iF "$LOOK_FOR" >> output
Since you're executing this command in a loop and overwriting file output every time, it might be blank in the end if very last command with grep doesn't find any matching line in unzip output.
You have three problems
Don't try to parse the output of ls. Instead just use for i in plugins/*source*.jar The major reason is that your script will completely and utterly break on any files that have spaces in their names. See this link for a litany of reasons why not to parse ls
You need to use >> instead of > as the latter will overwrite the output file on each iteration of the loop. The former will append to it
Use more quotes! You'll want to quote your variables to make sure they aren't subjected to word splitting
Also, you can inline the if test. So putting it all together we have:
#!/bin/sh
LOOK_FOR="DefaultProblem"
for i in plugins/*source*.jar
do
# echo "Looking in $i ..."
if unzip -p "$i" | grep -i "$LOOK_FOR" >> output #> /dev/null
then
echo ">>>> Found $LOOK_FOR in $i <<<<"
fi
done
You can redirect the output of the entire loop:
#!/bin/sh
LOOK_FOR="DefaultProblem"
FILES=`ls plugins/*source*.jar`
for i in $FILES ; do
# echo "Looking in $i ..." 1>&2
unzip -p $i | grep -i $LOOK_FOR
if [ $? == 0 ] ; then
echo ">>>> Found $LOOK_FOR in $i <<<<" 1>&2
fi
done > output
Note that I've redirected the diagnostic messages to stderr.
Instead of a for loop and an if conditional you can do everything in one find command
find /path/to/plugins -name "*source*.jar" -exec sh -c 'unzip -l "{}" | grep -q DefaultProblem' \; -print

Resources