1

This is what I'm trying to do:

I want to make a script that i can invoke either with counter_use in or counter_use out. If i type in i want a counter to add +1 to the numeric value inside a file called "counter", if I type out i want to subtract 1 from the file.

I also want the script to output Logged in if the value in counter are equal to or higher than 1 and Not logged in if the counter is equal to 0.

The last part is runnig if i hard code the counter to a specific number. The problem is the first part.

echo "In or out?"

read input > counterFile

if grep -q "in" counterFile
    then //what should I do here so that it adds +1 to a file called 
counter?

elif grep -q "out" counterFile
    then //what should I do here so that it subtracts -1 to a file called 
counter?

if [ $counter -ge 1 ]
    then
        echo "Logged in"

elif [ $counter -eq 0 ]
    then
        echo "Not logged in"

else
        echo "Wrong input"

fi
LinuxN00b
  • 33
  • 1
  • 1
  • 5

3 Answers3

2

romaric crailox's helpful answer contains many useful pointers, but the code can be streamlined to become a more idiomatic (Bash) solution:

#!/bin/bash

# Create the counter file on demand.
[[ -f counter ]] || echo 0 > counter

# Prompt until valid input is received.
while read -p 'In or out? ' input; do

  case $input in
    'in')
      # Update the counter file by incrementing the number it contains.
      perl -i -ple '++$_' counter
      break # valid input received, exit the loop
      ;;
    'out')
      # Update the counter file by decrementing the number it contains.
      perl -i -ple '--$_' counter
      break # valid input received, exit the loop
      ;;
    *)
      echo "Invalid input." >&2  # echo error to *stderr*
      # Stay in the loop to prompt again.
      ;;    
  esac

done

# Read the updated counter file and echo the implied status.
counter=$(< counter)
if (( counter >= 1 )); then
  echo 'Logged in.'
elif (( counter == 0 )); then
  echo 'Not logged in.'
else
  echo "Invalid state: counter is $counter" >&2
fi

Note:

  • The use of case ... esac to handle multiple conditions more succinctly than an if ... elif ... fi statement.

  • Outputting error messages to stderr with >&2

  • Use of a perl command to update file counter in place:

    • -i activates in-place updating
    • -ple automatically prints the (modified) input line, -l adds intelligent newline handing, and -e specifies the expression (script) to run (the following argument)
    • ++$_ / --$_ then simply increments / decrements the input line at hand ($_), which, thanks to -p, gets output automatically, and, thanks to -i, written back to the original file (loosely speaking; a new file is created that replaces the original).
  • Use of arithmetic evaluation ((( ... ))) to test numbers.

Community
  • 1
  • 1
mklement0
  • 382,024
  • 64
  • 607
  • 775
1

First problem is the use of read command. Try this

read -p "in or out ?" input
  • -p option is to specifie something to print to stdout
  • input is the name of shell script variable that will store user input

After this command, input variable will be in or out. Then you can test if input is in or out with an if expression :

if [ "$input" == "in" ] [...]

To add or substract 1 to value inside counter file, you can retrieve current value Inside file, add or substract 1 and write new value Inside file (I'm not sure you want to write new value. Try this :

crt_val=$(cat ./counter)
new_val=$(( crt_val + 1 ))
echo $new_val > ./counter

Counter file have to be present, so you can add, at the beginning of script

if [ -e ./counter ] ; then echo "0" > ./counter ; fi

Finally, code can be this :

# user entry
read -p "in or out ? " input

# initialize counter file
if [ ! -e ./counter ] ; then echo "0" > ./counter ; fi

# Doing what user entry ask to do
if [ "$input" == "in" ]
then
  echo "in"
  crt_val=$(cat ./counter)
  new_val=$(( crt_val + 1 ))
  echo $new_val > ./counter
elif [ "$input" == "out" ]
then
  echo "out"
  crt_val=$(cat ./counter)
  new_val=$(( crt_val - 1 ))
  echo $new_val > ./counter
else
  echo "Wrong input, try in or out"
  exit 1
fi

# Output
if [ $new_val -ge 1 ]
then
  echo "Logged in"
elif [ $new_val -eq 0 ]
then
  echo "Not logged in"
else
  echo "Wrong counter value"
fi

Be carefull, user entry have to be exactly in or out (case sensitive), and have to be no empty. To protect empty answer, try if [ "x$input" == "xin" ] [...]

Hope this help

romaric crailox
  • 564
  • 1
  • 3
  • 15
0
#!/bin/bash


echo "In or out?"

read c <&0  # reads from stdin file descriptor &0 is stdin

if [[ $c == 'In' ]] || [[ $c == 'in' ]];  
then
counter=$(<counter.txt) # reads counter from file
let "counter = counter +1"  # increases variable
echo "$counter" > 'counter.txt' # write new value to file overwriting the old
elif [[ $c == 'Out' ]] || [[ $c == 'out' ]];
then
counter=$(<counter.txt) # reads from file
let "counter = counter -1"
#echo "$counter" > 'counter.txt'
else
echo "wrong input..."
fi

Write to file, but overwrite it if it exists

https://askubuntu.com/questions/385528/how-to-increment-a-variable-in-bash/706683

http://ryanstutorials.net/bash-scripting-tutorial/bash-if-statements.php

Community
  • 1
  • 1
ralf htp
  • 9,149
  • 4
  • 22
  • 34
  • This doesn't really reliably count, as you have a race condition. You would need to lock the counter file during update. – user1934428 Apr 10 '17 at 14:26
  • can you explain this ? – ralf htp Apr 10 '17 at 15:41
  • You read the counter file, and later you write the updated counter file. If a second process runs this script simultaneously, it could read the counter file between your reading and your writing, and hence doesn't see your updated value yet. – user1934428 Apr 11 '17 at 15:43
  • when i have free time i will add a version that locks the file with `flock` utility ( https://linux.die.net/man/1/flock , http://stackoverflow.com/questions/22506857/locking-files-in-bash) you can edit the answer if you want ... – ralf htp Apr 11 '17 at 17:49