4

I have a simple one-liner that works perfectly in the terminal:

history | sort -k2 | uniq -c --skip-fields=1 | sort -r -g | head

What it does: Gives out the 10 most frequently used commands by the user recently. (Don't ask me why I would want to achieve such a thing)

I fire up an editor and type the same with a #!/bin/bash in the beginning:

#!/bin/bash
history | sort -k2 | uniq -c --skip-fields=1 | sort -r -g | head

And say I save it as script.sh. Then when I go to the same terminal, type bash script.sh and hit Enter, nothing happens.

What I have tried so far: Googling. Many people have similar pains but they got resolved by a sudo su or adding/removing spaces. None of this worked for me. Any idea where I might be going wrong?


Edit:

I would want to do this from the terminal itself. The system on which this script would run may or may not provide permissions to change files in the home folder.

Another question as suggested by BryceAtNetwork23, what is so special about the history command that prevents us from executing it?

Ranveer
  • 6,683
  • 8
  • 45
  • 92
  • 1
    I looked up this answer: http://stackoverflow.com/questions/4651437/how-to-set-a-bash-variable-equal-to-the-output-from-a-command and tried what was suggested with the `history` command. It still didn't work. I suppose a better question to ask, is what is special about `history` that prevents us from capturing its output in a script? – Aaron Feb 13 '14 at 18:37

3 Answers3

6

Looking at your history only makes sense in an interactive shell. Make that command a function instead of a standalone script. In your ~/.bashrc, put

popular_history() {
    history | sort -k2 | uniq -c --skip-fields=1 | sort -r -g | head
}
glenn jackman
  • 238,783
  • 38
  • 220
  • 352
  • Damn! Is there a workaround? Actually I'm creating this script for use by someone else. I need this to happen via a single bash script, without editing their ~/.bashrc – Ranveer Feb 13 '14 at 18:27
  • 1
    Then you have to tell them to `source script.sh` (or `. script.sh`) instead of executing it. No other way: the script has to run in the user's **current** shell, not in a non-interactive subshell. – glenn jackman Feb 13 '14 at 18:34
  • Work for what? It saves the output to a file but is otherwise identical. – tripleee Feb 13 '14 at 18:51
  • @Ranveer, do you mean will `bash script.sh` work if you just redirect inside the script? No, for all the reasons given. – glenn jackman Feb 13 '14 at 19:02
  • 2
    History expansion is only on by default in an interactive shell, but it can be enabled in a non-interactive shell with `set -o history`. The contents of `.bash_history` may need to be explicitly added to the history list of the current shell with `history -r ~/.bash_history`. – chepner Feb 13 '14 at 19:04
  • Seems the problem is fixed, but the current accept one is not 100% suitable for original request. So @chepner, you should answer it, then we can vote it. – BMW Feb 14 '14 at 03:10
  • 1
    While it's true you can accomplish the task in a non-interactive shell via a script, I agree with @glennjackman that this really is something you want to put in a function to use interactively. – chepner Feb 14 '14 at 14:07
4

To use history from a non-interactive shell, you need to enable it; it is only on by default for interactive shells. You can add the following line to the shell script:

set -o history

It still appears that only interactive shells will read the default history file by, well, default, so you'll need to populate the history list explicitly with the next line:

history -r ~/.bash_history

(Read the bash man page for more information on using a file other than the default .bash_history.)

chepner
  • 497,756
  • 71
  • 530
  • 681
  • But it's wacky to attempt to work around the fact that your interactive command history is only useful in an interactive shell. Maybe it could be argued that Bash doesn't need to disallow it by default like that, but the sane thing under the given circumstances is to go with (an adaptation of) @glennjackman's answer. – tripleee Feb 16 '14 at 10:15
  • For the very limited application of *viewing* the history, I might argue this is reasonable. But it's probably just as easy to work directly with the history file as it is to use the `history` built-in. – chepner Feb 16 '14 at 16:27
-1

History command is disabled by default on bash script, that's why even history command won't work in .sh file. for its redirection. Kindly redirect bash_history file inside the .sh file.

History mechanism can be enabled also by mentioning history file and change run-time parameters as mentioned below

#!/bin/bash
HISTFILE=~/.bash_history
set -o history 

Note: mentioned above two lines on the top of the script file. Now history command will work in history.

Siong Thye Goh
  • 3,518
  • 10
  • 23
  • 31
linux.cnf
  • 519
  • 6
  • 7