I want changes_summary to always be in format <x> files changed, <y> insertion(+), <z> deletions(-) where <x> <y> and <z> are some numbers, but diffstat misses insertions and/or deletions part if <y> and/or <z> is zero, I tried to make it print as <x> files changed 0 insertion(+), 0 deletions(-) always, is there a better or easy way to do this? I would like to change $changes_summary variable so I can use it later part of the script.
changes_summary=`diff -ur ./dir1 ./dir2 | diffstat | tail -1`
if ! echo $changes_summary | grep -q "insertions" && ! echo $changes_summary | grep -q "deletions" ; then
echo $changes_summary | awk '{print $1 " " $2 " " $3 " " "0 insertion(+)," " " "0 deletions(-)"}'
elif ! echo $changes_summary | grep -q "insertions" && echo $changes_summary | grep -q "deletions" ; then
echo $changes_summary | awk '{print $1 " " $2 " " $3 " " "0 insertion(+), "$4 " " $5 }'
elif echo $changes_summary | grep -q "insertions" && ! echo $changes_summary | grep -q "deletions" ; then
echo $changes_summary | awk '{print $1 " " $2 " " $3 " " $4 " " $5 "0 deletions(-)" }'
fi
Probably the closest you can get without some serious bash magic or an other language is something like the following.
changes_summary=`diff -ur ./dir1 ./dir2 | diffstat -s`
CC=$(echo "$changes_summary" | sed -n 's:\(.*[0-9]\+ .* changed\).*:\1:p')
II=$(echo "$changes_summary" | sed -n 's:.*\([0-9]\+ insertions\?\).*:\1:p')
DD=$(echo "$changes_summary" | sed -n 's:.*\([0-9]\+ deletions\?\).*:\1:p')
echo "${CC}, ${II:-0 insertions}(+), ${DD:-0 deletions}(-)"
Sed strips out the message corresponding to each stat. The -n suppresses the normal output, p prints only if a match is found. If not, then CC, II, DD will be empty, in which case the ${II:-...} pattern substitutes a default value.
From man bash:
${parameter:-word} Use Default Values. If parameter is unset or null,
the expansion of word is substituted. Otherwise, the value of
parameter is substituted.
Note that keeping the (s) with s\? might be an overkill for you.
The other option is that in bash you can check for containment with [[ $a =~ "b" ]] and use your original approach. It spares you the greps at least and "b" here can also be regex if you drop the quotes.
if ! [[ "$changes_summary" =~ "insert" ]]; then
awk ...
fi
You can also find the =~ in man bash.
Related
I am attempting to create a program in Unix that accesses a data file, adding, deleting, and searching within the file for names and usernames. With this if statement, I am attempting to allow the user to search for data in the file by the first field.
All of the data in the file uses uppercase letters, so I first must convert any text the user input from lowercase to uppercase letters. For some reason, this code is not working with both converting to uppercase and searching and printing the data.
How can I fix it?
if [ "$choice" = "s" ] || [ "$choice" = "S" ]; then
tput cup 3 12
echo "Enter the first name of the user you would like to search for: "
tput cup 4 12; read search | tr '[a-z]' '[A-Z]'
echo "$search"
awk -F ":" '$1 == "$search" {print $3 " " $1 " " $2 }'
capstonedata.txt
fi
This: read search | tr '[a-z]' '[A-Z]' will not assign anything to variable search.
It should be something like
read input
search=$( echo "$input" | tr '[a-z]' '[A-Z]' )
and it is better to use parameter expansion for case modification:
read input
search=${input^^}
If you use Bash, you can declare a variable to convert to uppercase:
$ declare -u search
$ read search <<< 'lowercase'
$ echo "$search"
LOWERCASE
As for your code, read doesn't have any output, so piping to tr doesn't do anything, and you can't have a newline before the file name in the awk statement.
Edited version of your code, minus all the tput stuff:
# [[ ]] to enable pattern matching, no need to quote here
if [[ $choice = [Ss] ]]; then
# Declare uppercase variable
declare -u search
# Read with prompt
read -p "Enter the first name of the user you would like to search for: " search
echo "$search"
# Proper way of getting variable into awk
awk -F ":" -v s="$search" '$1 == s {print $3 " " $1 " " $2 }' capstonedata.txt
fi
Alternatively, if you want to use only POSIX shell constructs:
case $choice in
[Ss] )
printf 'Enter the first name of the user you would like to search for: '
read input
search=$(echo "$input" | tr '[[:lower:]]' '[[:upper:]]')
awk -F ":" -v s="$search" '$1 == s {print $3 " " $1 " " $2 }' capstonedata.txt
;;
esac
Awk is not shell (google that). Just do:
if [ "$choice" = "s" ] || [ "$choice" = "S" ]; then
read search
echo "$search"
awk -F':' -v srch="$search" '$1 == toupper(srch) {print $3, $1, $2}' capstonedata.txt
fi
When I try to run this script this error appears : operating extra /home/ubuntu/Desktop/Destino/, and I do not know why , someone help me please.
#!/bin/bash
input="/home/ubuntu/Desktop/Output/SAIDA.txt"
dt=`date +"%Y%m%d%H%M%S"`
layout='C'
if [ -e "$input" ] ; then
header=$(head -n 1 $input)
export header
tail -n +2 $input | split -l 99 -d --additional-suffix=.txt \ --filter='{ printf %s\\n "$header"; cat; }' >/home/ubuntu/Desktop/Destino/$FILE - NOMENCLATURA_${dt}_
for arquivo in ´Is/home/ubuntu/Desktop/*.txt´
do
NOME= ´cat $arquivo | cut -d "." -f1´
touch/home/ubuntu/Desktop/Destino/$NOME.cfg
echo $dt > $NOME.cfg
echo $layout > $NOME.cfg
done
else
echo "The input file does not exist."
fi
You have some strange quote characters in your script. To substitute the output of a command, wrap it with $() or backticks, not ´ characters.
for arquivo in ´Is/home/ubuntu/Desktop/*.txt´
I guess Is was meant to be ls, but you left out the space after it. But there's no need to parse the output of ls, just use the wildcard directly.
for arquivo in /home/ubuntu/Desktop/*.txt
On this line:
tail -n +2 $input | split -l 99 -d --additional-suffix=.txt \ --filter='{ printf %s\\n "$header"; cat; }' >/home/ubuntu/Desktop/Destino/$FILE - NOMENCLATURA_${dt}_
you need to put the output filename in quotes because of the spaces.
tail -n +2 $input | split -l 99 -d --additional-suffix=.txt \ --filter='{ printf %s\\n "$header"; cat; }' >"/home/ubuntu/Desktop/Destino/$FILE - NOMENCLATURA_${dt}_"
Also, the FILE variable is not set, you need to assign that earlier.
On this line:
NOME= ´cat $arquivo | cut -d "." -f1´
you're again using the wrong type of quotes to capture the output of the command. Also, you must not have a space between = and the value you want to assign. It should be:
NOME=$(cat $arquivo | cut -d "." -f1)
There's no need to do export header. The variable is only being used in this script, not in any child processes.
How can I get this to work?
#!/bin/bash
SOMETHING=$(egrep '^ something' /some/dir/file.conf | awk -F '.' '{print $1}' | awk '{print $2}')
if [ $SOMETHING = 123 ]; then
echo "Found 123"
else
echo "Cannot find 123" && exit 1
fi
Results in grep complaining about a syntax error. It doesn't like the '^ something'
Your multiple commands with pipes can be simply replaced with the awk itself. Use following script:
SOMETHING=$(awk '/^ something/{print substr($4, 1, 3);}' somefile.conf)
if [ "$SOMETHING" = "123" ]; then
echo "Found 123"
else
echo "Cannot find 123" && exit 1
fi
EDIT: Looks like you've edited the question and your script after I posted my anser. Here is the modified awk command for you latest edit (don't do it again pls):
SOMETHING=$(awk -F "." '/^ something/{split($1, a, " "); print a[2]}' somefile.conf)
I've written a function to do some logging on different aspects of the files, folder, etc and I 'm going to have this automatically email members of my staff. All this is fine but I wouldn't mind some pointers and help to make the formation nicer - this will get sent out via mailutils as part of the script.
Just looking for some nice spacing tips,etc
function report(){
lsb_release -a
echo "OS: $(uname -s)"
echo "ARCH: $(uname -m)"
echo "VER: $(uname -r)"
echo "Apache running "
ps aux|grep -i apache2
echo "Showing if SSL is open"
apache2ctl -M | grep ssl
echo "Space on local disk"
df -h
echo "Showing permissions for the web folders"
echo $'*** /var/www// ***'
ls -l /var/www | awk '{print $1 " " $3 " " $4 " " $9}'
ls -l /var/www/user1 | awk '{print $1 " " $3 " " $4 " " $9}'
ls -l /var/www/user2 | awk '{print $1 " " $3 " " $4 " " $9}'
echo "Showing network status"
ifconfig eth0
echo " DNS "
tail /etc/resolv.conf
echo "Current workspaces set up on the local server "
grep user2 /var/www/temp/text.txt | grep -E -o '[0-9]+[0-9]'
}
Try piping the "column" command instead of or after using awk or cut.
ls -l | awk '{print $1" "$3" "$4" "$9}' | tail -n +2 | column -t
Check out the difference between "mount" and "mount | column -t" or "df -PH and df -PH | column -t"
If you want to concatenate columns of info with the same number or relational fields you can use process redirection and "paste."
paste -d ' ' <(cat /sys/class/scsi_host/host*/device/fc_host:host*/port_name) \
<(cat /sys/class/scsi_host/host*/device/fc_host:host*/speed) \
<(cat /sys/class/scsi_host/host*/device/fc_host:host*/port_state)
0x218000e05a0001aa 4 Gbit Online
0x218000e05a2001aa 4 Gbit Online
For multiple folders provided as input from the user, I'd like to count how many of the files and folders they contain have different permission settings as the container folder itself.
I've written the following shell code. Why does it display the rights, but not count anything?
#!/bin/sh
if [ ! -d $1 ]
then echo $1 nu este director
exit1
fi
ls -R $1 >temp
permission= ls -al $1 | cut -d" " -f1
for i in `cat temp`
do
perm= ls -l $i | cut -d" " -f1
if [ $permission -ne $perm ]
then n=`expr $n + 1`
fi
echo $n
done
You shouldn't use -ne for string comparisons. You need to do this:
if [ "$permission" != "$perm" ]
then
n=`expr $n + 1`
fi
You need to initialise n before you can increment it.
n=0
You need to fix your command substitution:
permission=$(ls -al $1 | cut -d" " -f1)
perm=$(ls -l $i | cut -d" " -f1)
exit1 should be exit 1
you want to use command substitution:
permission=$(ls -al $1 | cut -d" " -f1)
# ...
perm=$(ls -l $i | cut -d" " -f1)
You are not initializing your variable $n, so your call to expr expands to expr + 1 which is a syntax error. You should see lots of "expr: syntax error" messages on stderr. Just add the line n=0 before your loop and you should be fine.
Adding to other's answers:
exit1 should be exit 1