#!/usr/bin/env bash # Exit if any command fails set -e # Inform the user of the output they can expect. echo "common commands:" write_command_then_count() { # Get the command and count, which currently looks like: # '42 git commit' # Then write th e command with the count afterward local line="$1" local count=$(echo "${line}" | cut -d' ' -f1) local command=$(echo "${line}" | cut -d' ' -f2-) echo "${command} (${count})" } # The following variables control how the command runs. shell_binary="" # A place to store the shell binary value history_file="" # A place to store the history file path history_lines=1000 # The number of lines of history to search through command_count=${1:-10} # The number of common commands to show # Check whether you can determine the name of the shell binary shell_regex="([^/]+$)" if [[ $SHELL =~ $shell_regex ]]; then # Depending on the name of the shell binary, set the history filepath shell_binary=${BASH_REMATCH[1]} if [[ $shell_binary == "bash" ]]; then history_file=~/.bash_history elif [[ $shell_binary == "zsh" ]]; then history_file=~/.zsh_history fi fi # If you are searching through the bash history, you can look at the history file # to get the most common commands if [[ $shell_binary == "bash" ]]; then # Show the most commonly used commands commands=$(tail "${history_file}" -n ${history_lines} \ | sort \ | uniq -c \ | sed 's/^ *//' \ | sort -n -r \ | head -n ${command_count}) elif [[ $shell_binary == "zsh" ]]; then # Z shell shitory lines look like this: # : 1621135004:0;uname -a # Run the same command as above, and extract everything _after_ the # semicolon, which is the command text commands=$(tail "${history_file}" -n ${history_lines} \ | cut -d';' -f2 \ | sort \ | uniq -c \ | sed 's/^ *//' \ | sort -n -r \ | head -n ${command_count}) else # show a warning to the user that you don't know where the history file # is for their shell echo "Sorry, I don't know where to find the history file for '${SHELL}'" fi # Print each command, showing its order in the list # Commands are separated by newlines, so temporarily change IFS to loop over # each line of the commands counter=1 old_ifs=$IFS IFS=$'\n' for command in $commands do use_count=$(echo "$command" | cut -d' ' -f 1) use_command=$(echo "$command" | cut -d' ' -f 2) printf "$(tput bold; tput setaf 3)%-5s $(tput sgr0)$(tput setaf 6)%-5s $(tput sgr0)%-5s\n" "$counter" "$use_count" "$use_command" counter=$((counter + 1)) done IFS=$old_ifs