2

On the bash terminal if I execute the following for loop:

 for i in {1..5}; do echo $i;  done

The echo commands are not added to the history of the current shell. Is it because the commands in for (in do section) are run in subshell? If so is there a way to run them in the current shell instead? Or is it not possible because it's "running" for at the time?

Edit: Given it takes the entire for loop as one single compound command, if I remove the for loop and write the individual commands in five lines shouldn't all five be added to history?

I did the following:

#!/bin/bash

set -o history

    var=5
    echo $((var--)) 
    echo $((var--)) 
    echo $((var--)) 
    echo $((var--)) 
    echo $((var--)) 

and ran the script using source. Still in history it shows only one echo statement echo $((var--)) and not all five. On the other hand, if instead of five echo $((var--)) I put five echo 5, echo 4, ... echo 1 commands all five are added to history.

Why?

9
  • 1
    for i in {1..5}; do history -s echo $i; done see help history – Jetchisel Apr 17 '20 at 10:29
  • great. doing this the echo commands are added to history but oddly they don't output on current shell (nothing echoes.. l – Lavya Apr 17 '20 at 10:35
  • 6
    The individual echo commands are not added because the command being run is the compound for loop command (which is added to the history). It has nothing to do with subshells. – Kusalananda Apr 17 '20 at 10:39
  • 1
    No need for a loop, echo 1; echo 2; in one line is a single command in history, too ... – pLumo Apr 17 '20 at 10:44
  • 1
    This is because you have ignoredups in $HISTCONTROL. – Arkadiusz Drabczyk Apr 17 '20 at 22:39
1

Your script wouldn't save history to ~/.bash_history at all in the first place unless you exported $HISTFILE before running it. As it says in man bash this is because:

If HISTFILE is unset, or if the history file is unwritable, the history is not saved.

HISTFILE is not an environment variable, it's a shell variable and therefore not available in scripts which are child processes. And even if you ran these commands

$    var=5
$    echo $((var--))
$    echo $((var--))
$    echo $((var--))
$    echo $((var--))
$    echo $((var--))

(note the whitespaces after the prompt) in an interactive session and not a script they wouldn't be saved to ~/.bash_history in practice neither because popular Linux distributions such as Ubuntu set HISTCONTROL to ignorespace or ignoreboth (which is an alias for ignorespace and ignoredups) to not save commands that start with one or more whitespaces. This is especially useful if you work on a shared server with other users and you intentionally don't want to save a given command to the history so that other people could see it, for example because it contains your password or other sensitive information.

But even if there were no whitespaces before the command:

$ var=5
$ echo $((var--))
$ echo $((var--))
$ echo $((var--))
$ echo $((var--))
$ echo $((var--))

you would most probably end up with only a single echo $((var--)) entry in ~/.bash_history because HISTCONTROL commonly contains ignoredups or the aforementioned ignoreboth. All of this is described under HISTCONTROL section in Bash manpage you can invoke with man bash on your system.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.