Reputation: 383
Below is my input file, that I need to pass and find out whose value is above 10G.
100G tom
30G kelly
40G messy
50G Kyrie
1G james
.5G curry
2.4 sweety
57G muller
6G kevin
Here is the code attempt in bash.
for i in `cat test.txt`;
do
k=$(echo $i | awk '{print $1}' | grep G | cut -d'G' -f1;);
j=$(echo $i | grep -v '^[0-9]';);
int=${k%.*};
if [[ -z $int ]];
then continue
else
if [ $int -ge 10 ];
then
# du -sh
echo $j
# sudo du -sh $j
fi
fi
# echo $int
done
It's producing results if more then 10, i.e if [ $int -ge 10 ]
is working. I am not able to print the name if value is more then 10Gig in file. To put it simple my expected result is
100G tom
30G kelly
40G messy
50G Kyrie
57G muller
Upvotes: 1
Views: 953
Reputation: 189327
Don't read lines with for
. The idiomatic way to read a line with two fields is
while read -r first second; do
: ... things
done <test.txt
But of course, you can simply do
awk '($1 ~ /G$/ && $1+0>10) || $1 ~ /[TP]$/' test.txt
(I added terabytes and petabytes just to show you how it's done if you should need it.)
Generally, looping over the lines in a file one by one in the shell is an antipattern which suggests you should try sed
or Awk instead unless you really need the body of the loop to be shell script.
Upvotes: 1
Reputation: 21492
Using numfmt
tool (which is a part of GNU Coreutils):
while read -r line
do
n=$(numfmt --from=auto --format %f "${line%% *}")
(( $(bc <<< "$n > 10000000000") )) && printf '%s\n' "$line"
done < test.txt
The loop reads test.txt
file line by line; -r
option prevents backslashes from being interpreted. Since IFS
variable is not modified, the line
is trimmed, and we can safely extract the first column with an expression like "${line%% *}"
which removes the first space and everything after it leaving us only the first column.
The numfmt
command converts the first column to floating point format.
Since Bash does not support floating point numbers, bc
is used to check if $n
is greater than 10000000000. If it is, the command exits with zero status (indicating success), and the printf
command is called.
Obviously, you can use the code above with other common units such as K
, Ki
, M
, Mi
etc.
Since sizes of real files are expressed in integers, you can get rid of the "floating point arithmetic" in the following way:
declare -i n=$(numfmt --from=auto --format %.0f "${line%% *}")
(( $n > 10000000000 )) && printf '%s\n' "$line"
Zero precision format %.0f
means that numfmt
will return the result as (rounded) integer. The second line checks if $n
is greater than 10000000000 using arithmetic expansion.
On Mac OS, the numfmt
tool is provided by GNU Coreutils package; the name of executable is gnumfmt
.
Upvotes: 2
Reputation: 791
Can you try this :
bash-4.4$ cat filename
100G tom
30G Kely
40G messy
50G kyrie
1G james
.5G curry
2.4 sweety
57G muller
6G kevin
bash-4.4$ cat script.sh
cat filename|grep "G">tempFile
while read line;
do
size=echo $line|awk 'BEGIN{FS="G"}{print $1}'
check=echo $line|grep "^[0-9]"|wc -l
if [ $check -ne 0 ]
then
if [ $size -gt 10 ]
then
echo $line
fi
fi
done
bash-4.4$ ./script.sh
100G tom
30G Kely
40G messy
50G kyrie
57G muller
You can remove the tempfile at the end of the script if no longer required. Or it will get overwritten every time you run the script.
hope this helps.
Upvotes: 0
Reputation: 18351
awk 'BEGIN{FS="G| "} $1>10' inputfile
100G tom
30G kelly
40G messy
50G Kyrie
57G muller
This is using G
as field separator and $1>10
is the condition to print the whole record. A while space is also used as field seprator to deal with the records like 2.4 sweety
Note: This assumes, that your input is having records only in Gigs.
Upvotes: 3