2

I have user settings in my shell script. How can I ask user for input and remember it? In example i have in code:

ALTERNATEMEMORY="false"

I need to ask user for input (when running script in 'configure' mode):

echo "Use alternate memory?"
select yn in "true" "false"; do
    case $yn in
        Yes ) [permament save ALTERNATEMEMORY as "true"];;
        No ) [permament save ALTERNATEMEMORY as "false"];;
    esac
done

Script should ask user as above, read his input, and depending of choice set ALTERNATEMEMORY to corresponding state. Next time when running script (not configuring, just running) it should remember that setting. What should I put in these square brackets?

If I'm making mistakes when posting question, please forgive me - this is first time when I'm using stackoverflow.

Bielecki
  • 131
  • 1
  • 2
  • 13
  • You could use a text file to store the user settings but I'm not sure if this is the best method to remember settings. – sjsam Nov 27 '15 at 07:21
  • maybe using an environment variable (will not persist after closing a terminal and will not be accessible from another bash instance) – Zermingore Nov 27 '15 at 08:00

2 Answers2

3

The standard way to remember a setting from one run to the next, even after reboots, is to use a configuration file. For system-wide settings, these configuration files are usually in /etc and could be named, for example, /etc/myprog.conf. For user-specific settings, the file is usually in the home directory with a name that starts with ., such as $HOME/.myprog.conf. Pick one of those paths and create the configuration file:

echo "ALTERNATEMEMORY=false" >path/myprog.conf

Now, have the configuration section of your script update that file as desired:

echo "Use alternate memory?"
select yn in "true" "false"; do
    case "$yn" in
        true)
           sed -i '/ALTERNATEMEMORY/ s/.*/ALTERNATEMEMORY=true/' path/myprog.conf
           break
           ;;
        false)
           sed -i '/ALTERNATEMEMORY/ s/.*/ALTERNATEMEMORY=false/' path/myprog.conf
           break
           ;;
    esac
done

In the above, we used sed -i to update the file in-place. This works on linux. If you are on a BSD system (OSX), then you will need to add two quotes to that command like sed -i "" ...

Doing substitutions with an arbitrary string

If we want to set ALTERNATEMEMORY to have the value $sel where sel is a shell variable containing arbitrary characters, then we need to escape them before doing the substitution. This can be done as follows (assuming the shell is bash):

escaped_sel=$(sed 's/[&/\]/\\&/g' <<< "$sel")
sed -i "/ALTERNATEMEMORY/ s/.*/ALTERNATEMEMORY=$escaped_sel/" path/myprog.conf
Community
  • 1
  • 1
John1024
  • 109,961
  • 14
  • 137
  • 171
  • Thank You for that tip on BSD – sjsam Nov 27 '15 at 08:35
  • And how I can call settings from .conf file into my script? – Bielecki Nov 30 '15 at 03:02
  • @Bielecki The form that we have used for the file is valid as a shell script. Consequently, you can simply use `source path/myprog.conf`. This assigns shell variable `ALTERNATEMEMORY` to the value given in the file. – John1024 Nov 30 '15 at 03:12
  • Okay, I got it. And what if I need to enter my own variable, eg. `TIMEZONE`? I tried to `read sel`, and then `sed -i '/TIMEZONE/ s/.*/TIMEZONE=$sel/' ~/.file.conf` but then, after executing, inside that config I got `TIMEZONE=$sel` :/ – Bielecki Nov 30 '15 at 04:41
  • That is because shell variables are not expanded inside single quotes. As long as `$sel` does not contain any sed-active characters, try: `sed -i "/TIMEZONE/ s/.*/TIMEZONE=$sel/" ~/.file.conf` – John1024 Nov 30 '15 at 06:00
  • Unfortunately it does. In example in code I have `TIMEZONE='Europe/Warsaw'`. I assume that slash character would have to be backslashed, but I don't want to require users to backslash every single special character inside reconfiguration script. – Bielecki Dec 01 '15 at 01:01
  • OK. No problem. Use `sed -i "/TIMEZONE/ s#.*#TIMEZONE=$sel#" ~/.file.conf `. If that doesn't suffice, you can replace the `#` with any character that you know is not going to be in your `$sel`. (On the other hand, if there is no such character, let me know.) – John1024 Dec 01 '15 at 01:31
  • It was fine until now. Today I came across a problem that I need allow user to enter any character into `$sel`. What command do I have to use? – Bielecki Dec 05 '15 at 21:52
  • 1
    @Bielecki OK. I just added to the end of the answer the code needed to handle arbitrary characters. – John1024 Dec 06 '15 at 00:14
0

Have a mem.conf file with the below lines

UNSET
TRUE

First line can be SET/UNSET which is to check if user has already configured and second line can be TRUE/FALSE which is to check whether to use alternate memory.

Initially the first line should be set to UNSET.

Then write the script configure.sh like below :

is_set=`head -n1 mem.conf`
if [[ $is_set == "SET" ]]
then
{
echo "Your have already configured the settings."
}
else
{
echo "Use Alternate memory?"
options=("TRUE" "FALSE" "QUIT")
select opt in "${options[@]}"
do
    case $opt in
        "TRUE")
            echo "SET" > mem.conf
            echo "TRUE" >> mem.conf
            echo "Configuration Saved !!"
            break;
            ;;
        "FALSE")
            echo "SET" > mem.conf
            echo "FALSE" >> mem.conf
            echo "Configuration Saved !!"
            break;
            ;;
        "QUIT")
            echo "Seems like you have not made up your mind yet !"
            echo "Please come back later."
            break;
            ;;
        *) echo "invalid option"
            ;;
    esac
done
}
fi
echo "Configuration File : "`pwd`"/mem.conf"

The advantage here is that you could force edit mem.conf to start from scratch.

sjsam
  • 21,411
  • 5
  • 55
  • 102