54

I would like to know which command I use the most on the command line. I would like to know so I can improve my use of the command line. If I know which command I use the most, I can then read more about them try and figure out better ways to use them.

I know history keeps a list of all the previous commands I typed. How would I process it to see a list of the top 10 or 20 most used commands.

2
  • Yes I did just post this question to answer it. It is just so interesting that I though the superuser community would really find it interesting.
    – nelaaro
    Feb 25, 2011 at 12:12
  • 1
    Nothing at all wrong with posting questions to answer yourself. It makes a handy bookmark, and if you're on the wrong track you'll soon hear about it!
    – Ken
    Jul 8, 2011 at 14:31

11 Answers 11

72

I just saw this post on http://linux.byexamples.com/

Basically you use a simple one line awk script

history | awk '{CMD[$2]++;count++;}END { for (a in CMD)print CMD[a] " " CMD[a]/count*100 "% " a;}' | grep -v "./" | column -c3 -s " " -t | sort -nr | nl |  head -n10

A full explanation can be found at the link above.

Example of out put on my machine is:

 1  211  21.1%  ls
 2  189  18.9%  sudo
 3  58   5.8%   man
 4  52   5.2%   cd
 5  43   4.3%   ping
 6  40   4%     apropos
 7  34   3.4%   less
 8  22   2.2%   cat
 9  18   1.8%   which
10  18   1.8%   aspell
4
  • 4
    On my OSX, the output of history is different, so I just needed to change the first $2 to $4 and this works.
    – Liam
    May 10, 2016 at 21:40
  • This could be improved by adding (or checking for) a HISTTIMEFORMAT variable assignment (as this will change history ouput), and testing for variable assignments or subshells at the beginning of the command, e.g. man, (man, and PAGER=less man should all be counted under man. Dec 4, 2019 at 16:58
  • @Liam or you can add HISTTIMEFORMAT="" before the command: HISTTIMEFORMAT="" history | awk '{CMD[$2]++;count++;}END { for (a in CMD)print CMD[a] " " CMD[a]/count*100 "% " a;}' | grep -v "./" | column -c3 -s " " -t | sort -nr | nl | head -n10
    – user383438
    May 7, 2020 at 16:36
  • This works for bash. For fish, change $2 to $1. Jun 30, 2023 at 3:09
20
awk '{print $1}' ~/.bash_history | sort | uniq -c | sort -n

The awk command will print the first string from ~/.bash_history (not showing command options or arguments), then sort will order all lines alphabetically, then "uniq -c" will remove duplicated lines (your typed commands) and count them, and the last sort will order your commands by the count number returned by uniq.

3
  • You can also add -r at the end of the command to sort them in the reversed order and | head -10 to limit the number of results. Dec 26, 2016 at 17:36
  • 1
    I had to do "$HISTFILE" instead of ~/.bash_history because on my system the file was named differently
    – user383438
    May 7, 2020 at 16:37
  • Only works for bash. Jun 30, 2023 at 3:09
11

You can use the hash command in your terminal, which keeps a hash entry of every command that you use along with the number of hits and based on the hits you can sort them out and process.

Check this article for more information.

8

For a more general answer, enable "process accounting" on your system. You can get not just frequency of use, but aggregate CPU, memory, and I/O stats.

0
6

The scripts in the other answers only count the first command executed in each command line; they do not include commands executed after pipes (i.e. ' | '). For example, if this line itself was in your bash history:

awk '{print $1}' ~/.bash_history | sort | uniq -c | sort -n

then in the returned summary of most-executed commands, 'sort' and 'uniq' and the second 'sort' would not be included, as they weren't the first token in the line.

Building on the answer from nelaar, it suffices to first split the lines in your bash history on every pipe:

sed 's/|/\n/g' ~/.bash_history | awk '{CMD[$1]++;count++;}END { for (a in CMD)print CMD[a] " " CMD[a]/count*100 "% " a;}' | grep -v "./" | column -c3 -s " " -t | sort -nr | nl |  head -n10
6

A fun addition would be a bar chart of the counts:

history | tr -s ' ' | cut -d ' ' -f3 | sort | uniq -c | sort -n | tail | perl -lane 'print $F[1], "\t", $F[0], " ", "▄" x ($F[0] / 12)'

Output:

man     226 ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄
cat     230 ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄
rm      235 ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄
ls      240 ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄
aura    273 ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄
mv      362 ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄
sudo    534 ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄
vi      611 ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄
git     693 ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄
cd      754 ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄

Long commands will offset the spacing.

2
  • Any idea on how to make long commands not offset the spacing? Oct 7, 2018 at 13:13
  • @fortunate_man Unfortunately not, but I am not very familiar with perl, so you might very well get an answer if you ask that as a new question. I tried searching for how to print fixed width, but didin't find anything immediately helpful, and the function documentation was not much help either. You might need to use printf or sprintf instead of print. Oct 7, 2018 at 18:43
2

Use $ history | awk '{CMD[$2]++;count++;}END { for (a in CMD)print CMD[a] " " CMD[a]/count*100 "% " a;}' | grep -v "./" | column -c3 -s " " -t | sort -nr | nl | head -n10 to get a list of your top 10 commands.

Example:

 1  272  27.2%  svn
 2  227  22.7%  cd
 3  159  15.9%  sudo
 4  57   5.7%   ll
 5  52   5.2%   mc
 6  32   3.2%   rm
 7  23   2.3%   mkdir
 8  19   1.9%   exit
 9  13   1.3%   subl
10  13   1.3%   find
1
  • 1
    How is this different from the accepted answer? Oct 7, 2018 at 13:16
1

You can fashion the above awk answer from @nelaar into a nice bash script:

#!/bin/bash
HISTFILE=~/.bash_history
set -o history
history | awk '{CMD[$2]++;count++;}END { for (a in CMD)print CMD[a] " " CMD[a]/count*100 "% " a;}' | grep -v "./" | column -c3 -s " " -t | sort -nr | nl |  head -n10
1

Well this is a modified version of the command "Неделчо Христов" copied and pasted here.... if you have secured or date stamped your bash history then you will have a faulted output

This will do you better using this:

awk '{CMD[$1]++;count++;}END { for (a in CMD)print CMD[a] " " CMD[a]/count*100 "% " a;}' .bash_history | grep -v "#" | sort -nr | nl | column -c3 -s " " -t | head -n 20
1

If you're using Oh My Zsh! this feature is already there. Just type

zsh_stats

To get a list of the top 20 commands and how many times they have been run.

Source: https://github.com/ohmyzsh/ohmyzsh/wiki/Cheatsheet

1

If you wanna see the commands with arguments, you can try this:

history | awk '{$1="";CMD[$0]++;count++;}END { for (a in CMD)print CMD[a] " " CMD[a]/count*100 "% " a;}' | sort -nr | nl |  head -n10
➜ history | awk '{$1="";CMD[$0]++;count++;}END { for (a in CMD)print CMD[a] " " CMD[a]/count*100 "% " a;}' | sort -nr | nl |  head -n10
     1  689 12.2992%  l
     2  406 7.24741%  cd ..
     3  292 5.21242%  ssh dakv.aka.xx
     4  239 4.26633%  gs
     5  230 4.10568%  cr
     6  186 3.32024%  ls
     7  183 3.26669%  bbc
     8  159 2.83827%  gc --amend
     9  153 2.73117%  bb
    10  106 1.89218%  cd Service

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .