I have been working on this all morning with no luck. I need the results to be all on one line comma delimited. Some portions were working fine but once I added the read it feel apart!
INPUT=steamIPs.csv
OLDIFS=$IFS
IFS=,
[ ! -f $INPUT ] && { echo "$INPUT file not found"; exit 99; }
while read router contact address
do
myvar="$ip
$router
$contact
$address"
echo "$myvar" | paste -s -d','
OUTPUT=`snmpget $ip -c public -v 1 sysuptim`
echo ${OUTPUT#*:} | tr -d ' '
done < $INPUT
IFS=$OLDIFS
You're working too hard:
if [[ ! -f "$INPUT" ]]; then
echo "$INPUT file not found"
exit 99
fi
while IFS=, read -r router contact address; do
myvar="$ip,$router,$contact,$address"
echo "$myvar"
done < "$INPUT"
Related
This is part of my code that I working to find a word in a remote server connecting via ssh to that server
filename=test.repo
word=fail
exists=$(grep -c $word $filename)
file_server=$1
for i in $(cat $file_server)
do echo ''; echo $1 ;
ssh $i "printf '\e[33m'; hostname; printf '\e[0m\n]' ;
cd /etc/yum.repos.d/;
grep -c $word $filename;
echo $exists;
if [[ $exists -gt 0 ]];
then printf 'Keyword found, cleanup starts \n';
else printf ''$word', was not found, nothing to do here with '$filename'. \n';
fi"
done
This works with just the Do command, but if I add the if [[$exist -gt 0]]; , this got an error
bash: -c: line 4: conditional binary operator expected
bash: -c: line 4: syntax error near ;' bash: -c: line 4: if [[ -gt 0]]; '
any suggestion
This line should be cut from the beginning of the script:
exists=$(grep -c $word $filename)
And replace the call to grep inside the loop.
What I do, with some help of a colleague to fix this avoid using the variable on the ssh session.
file_server=$1
filename=testfile.repo
keyword=testword
if [[ -z $1 ]]
then
printf "\t\e[0;31m==================== ERROR ======================\n"
printf "\tServer list not found\e[0;0m\n"
exit 1
fi
for i in $(cat $file_server)
do echo ''; echo $1 ;
ssh $i "printf '\e[33m'; hostname; printf '\e[0m\n';
cd /etc/yum.repos.d/;
if grep -q $keyword $filename;
then
printf '\e[33m$keyword found, cleanup starts\e[0m\n';
sed -i.BAK '/^failovermethod=/d' $filename
grep failovermethod $filename;
printf '\e[33mBackup file created with the $keyword with this name $filename.BAK\e[0m\n';
grep 'failovermethod' pgdg-redhat-all-test.repo.BAK;
else
printf '\e[33m${keyword^^}\e[32m, was not found, nothing to do here. \e[0m\n';
fi;";
done
Here is my code:
f="\bkg\inp.txt"
while IFS='' read -r line || [[ -n "$line" ]]; do
IFS='|' read -r -a array <<< "$line"
#echo "${array[0]}"
if [ "${array[2]}" == "Sangamithra" ]; then
printf "%s" "${array[2]}|" "${array[1]}|"${array[0]}"
fi
done < "$f"
I know what the error is...
Since I am new to shell scripting..
I found the code in stackoverflow where we split a string and put into array - But the <<< part is causing problem showing Syntax error : Redirection unexpected..
Now wht should be the replacement for "<<<" in shell script or I have to choose any other way?I am not very much aware of all the syntaxes so could not replace..
Any help is very much appreaciated!!
The alternative for <<< "STRING" is echo "STRING" but if you pipe
the output of echo to the read command as echo "$line" | read ..,
read will be invoked in subshell,
in which created variables are not accessible from outside of the subshell.
Then please try:
f="\bkg\inp.txt"
while IFS='' read -r line || [[ -n "$line" ]]; do
IFS='|' read -r -a array < <(echo "$line")
if [ "${array[2]}" == "Sangamithra" ]; then
printf "%s" "${array[2]}|${array[1]}|${array[0]}"
fi
done < "$f"
If you are executing sh, not bash, the script
above will also complain about the redirect.
Then please consider to switch to bash, or try the following sh compliant
version:
#!/bin/sh
f="\bkg\inp.txt"
while IFS='' read -r line || [ -n "$line" ]; do
IFS="|" set -- $line
if [ "$3" = "Sangamithra" ]; then
printf "%s" "$3|$2|$1"
fi
done < "$f"
Hope this helps.
Although I was able to figure out my first script and get it to run, I am having issues with my second script. Basically I need to retrieve my deleted files and restore them in my created home directory. I was able to get some of question 2, and all of 3 and 4 to work successfully. The issue I have with question 2 is if I type up the file that I want to restore, it will pull up the file and inode number which is fine. However, if I run the script without the desired file, it will show a bunch of inodes and the command "Missing Operand". The missing operand command is one that I want since I created it in order to test that the files I want to restore exist. I have attached my code below. Again, I wonder what I got wrong. I did some of the suggestions shellcheck offered but I still got the same results.
Here is my code:
#!/bin/bash
#2.
fileName=$1
inode=$(ls -i $1 | cut -d " " -f1)
echo "safe_rm_restore $1_$inode"
#3.
function movingfile(){
if [ -e $HOME/deleted ] ;
then
mv $1_$inode $HOME/deleted $(grep $1 $HOME/.restore.info | cut -d" " -f3)
fi
}
movingfile $1
#4.
function safe(){
filename=$1
if [ ! -e $1 ] ;
then
echo "safe_rm_restore :cannot restore '$1': No such file or directory"
exit 1
elif [ $# -eq 0 ] ;
then
echo "safe_rm_restore: cannot restore '$1' : Missing operand"
exit 1
fi
}
safe $1
##5.
function restoreFile(){
if [ -e $(grep $1 $HOME/.restore.info | cut -d" " -f2) ] ;
then
read -p "File currently exists. Do you want to overwrite y/n?: word"
if [[ $word = "yes" || $word = "Y" || $word = "y" ]] ;
then
rm $(grep $1 $HOME/.restore.info | cut -d" " -f2)
mv $HOME/deleted $(grep $1/.restore.info | cut -d" " -f2)
fi
if [[ $word = "n" ]] ;
then
rm $1
exit 0
else
echo "Invalid Option"
exit 1
fi
fi
}
restoreFile $1
##6.
function restored(){
remove=$(grep -v $1 $HOME/.restore.info | tee $HOME/.restore.info)
if [[ ! -e $HOME/deleted && -e $(grep $1 $HOME/.restore.info | -d":" -f2)]];
then
$remove
fi
}
restored $1
I've followed the suggestions that you all gave me (and it moved me towards the right direction) but I still had some issues getting my operations to fully work. For instance, if no file name was given, my script was supposed to say Missing Operand but instead it gives all inode numbers in my file and my script freezes for sometime. Here is my updated second bash script. The indention looks great from my UNIX system but is somehow skewed when I transfer it on here. Thank you again!
#!/bin/bash
##2.
fileName="$1"
inode="$(ls -i $1 |cut -d" " -f1)"
echo "safe_rm_restore $1_$inode"
touch "$1"
##3.
movingfile(){
if [ -e $HOME/deleted ] ;
then
touch $1_$inode
mv $1_$inode $HOME/deleted $(grep $1 $HOME/.restore.info | cut -d" " -f4)
else
exit 1
fi
}
movingfile $1
##4.
safe(){
filename=$1
if [ ! -e $1 ] ;
then
echo "safe_rm_restore :cannot restore '$1': No such file or directory"
exit 1
elif [ $# -eq 0 ] ;
then
echo "safe_rm_restore: cannot restore '$1' : Missing operand"
exit 1
fi
}
safe $1
##5.
restoreFile(){
if [ -e $(grep $1 $HOME/.restore.info | cut -d" " -f4) ] ;
then
read -p "File currently exists. Do you want to overwrite y/n?:" word
if [[ $word = "yes" || $word = "Y" || $word = "y" ]] ;
then
mv $1_$inode $HOME/project $(grep $1/.restore.info | cut -d" " -f4)
fi
if [[ $word = "n" ]] ;
then
rm -r $1_$inode
exit 0
else
echo "Invalid Option"
exit 1
fi
fi
}
restoreFile $1
##6.
restored(){
remove=$(grep -v $1 $HOME/.restore.info | tee $HOME/.restore.info)
if [[ ! -e $HOME/deleted && -e $(grep $1 $HOME/.restore.info |cut -d":" -f4) ]];
then
$remove
fi
}
restored $1
I need to extract entries from a log file and put them on an errors file.
I don't want to duplicate the entries on the errors file every time that the script is run, so I create this:
grep $1 $2 | while read -r line ; do
echo "$line"
if [ ! -z "$line" ]
then
echo "Line is NOT empty"
if grep -q "$line" $3; then
echo "Line NOT added"
else
echo $line >> $3
echo "Line added"
fi
fi
done
And is run using:
./log_monitor.sh ERROR logfile.log errors.txt
The first time that the script runs it finds the entries, and create the errors file (there are no errors file before).
The next time, this line never found the recently added lines to the errors file,
if grep -q "$line" $3;
therefore, the script adds the same entries to the errors file.
Any ideas of why this is happening?
This most likely happens because you are not searching for the line itself, but treating the line as regex. Let's say you have this file:
$ cat file
[ERROR] This is a test
O This is a test
and you try to find the first line:
$ grep "[ERROR] This is a test" file
O This is a test
As you can see, it does not match the line we're looking for (causing duplicates) and does match a different line (causing dropped entries). You can instead use -F -x to search for literal strings matching the full line:
$ grep -F -x "[ERROR] This is a test" file
[ERROR] This is a test
Applying this to your script:
grep $1 $2 | while read -r line ; do
echo "$line"
if [ ! -z "$line" ]
then
echo "Line is NOT empty"
if grep -F -x -q "$line" $3; then
echo "Line NOT added"
else
echo $line >> $3
echo "Line added"
fi
fi
done
And here with additional fixes and cleanup:
grep -e "$1" -- "$2" | while IFS= read -r line ; do
printf '%s\n' "$line"
if [ "$line" ]
then
echo "Line is NOT empty"
if grep -Fxq -e "$line" -- "$3"; then
echo "Line NOT added"
else
printf '%s\n' "$line" >> "$3"
echo "Line added"
fi
fi
done
PS: this could be shorter, faster and have a better time complexity with a snippet of awk.
There's no need to check for blank lines; the first grep only checks lines with the word "ERROR", which cannot be blank.
If you can do without the diagnostic echo messages, pretty much the whole of that code boils down what might be done using two greps, a bash process substitution, sponge, and touch for the first-run case:
[ ! -f $3 ] && touch $3 ; grep -vf $3 <(grep $1 $2) | sponge -a $3
I am trying to write a batch file which checks if the file names present in a text file are present in a folder.
I have a folder called PAN where i have a text file named as PRAS_filelist.txt which stores all the file names. And a folder PRAS in which all my files are present.
My requirement is it should scan the folder and at the end, it should populate a error message in a file PRAS_PP_ERROR_LOG. but now it is coming out if any one file is not present since i have used exit.
Below is the code
`rm -f ../SessLogs/PRAS_PP_ERROR_LOG`
for i in `cat ./PAN/PRAS_filelist.txt`
do
file_name=$i
if [ -e ./PAN/PRAS/"$file_name"_* ]
then
if [ -s ./PAN/PRAS/"$file_name"_* ]
then
a=`sed -n '1p' ./PAN/PRAS/"$file_name"_*|cut -d'|' -f1`
b=`sed -n '$p' ./PAN/PRAS/"$file_name"_*|cut -d'|' -f1`
if [ "$a" == "H" ] && [ "$b" == "T" ]
then
trailer_record=`sed -n '$p' ./PAN/PRAS/"$file_name"_*|cut -d'|' -f2`
record_count=`wc -l ./PAN/PRAS/"$file_name"_*|cut -d' ' -f1`
r_c=`expr $record_count - 1`
if [ $trailer_record -eq $r_c ]
then
`cp ./PAN/PRAS/"$file_name"_* ./PAN/PRAS/STANDARDIZE/"$file_name"`
`sed -i '$d' ./PAN/PRAS/STANDARDIZE/"$file_name"`
else
echo "ERROR in file $file_name: Count of records is $r_c and trailer is $trailer_record">../SessLogs/PRAS_PP_ERROR_LOG
fi
else
echo "ERROR in file $file_name: header or trailer is missing">../SessLogs/PRAS_PP_ERROR_LOG
exit 1
fi
else
echo "ERROR in file $file_name: empty file">../SessLogs/PRAS_PP_ERROR_LOG
exit 1
fi
else
echo "ERROR: $file_name doesnot exist">../SessLogs/PRAS_PP_ERROR_LOG
exit 1
fi
done
refactoring your code a bit:
One odd thing is that you claim to have a list of filenames, but then you append an underscore before you check the file exists. Do the actual filenames actually have underscores?
#!/bin/bash
shopt -s nullglob
logfile=../SessLogs/PRAS_PP_ERROR_LOG
rm -f $logfile
while read file_name; do
files=( ./PAN/PRAS/${file_name}_* )
if (( ${#files[#]} == 0 )); then
echo "ERROR: no files named ${file_name}_*"
continue
elif (( ${#files[#]} > 1 )); then
echo "ERROR: multiple files named ${file_name}_*"
continue
fi
f=${files[0]}
if [[ ! -s $f ]]; then
echo "ERROR in file $f: empty file"
continue
fi
a=$(sed '1q' "$f" | cut -d'|' -f1)
b=$(sed -n '$p' "$f" | cut -d'|' -f1)
if [[ "$a" != "H" || "$b" != "T" ]]; then
echo "ERROR in file $f: header or trailer is missing"
continue
fi
trailer_record=$(sed -n '$p' "$f" | cut -d'|' -f2)
r_c=$(( $(wc -l < "$f") - 1 ))
if (( trailer_record == r_c )); then
sed '$d' "$f" > ./PAN/PRAS/STANDARDIZE/"$file_name"
else
echo "ERROR in file $f: Count of records is $r_c and trailer is $trailer_record"
fi
done < ./PAN/PRAS_filelist.txt | tee $logfile