Jacquelyn.Marquardt
Jacquelyn.Marquardt

Reputation: 630

Execute command after every command in bash

I want to print the date after every bash command I run.

This could help me understand how much a command took to execute when I am away from keyboard.

I know I could do

`DATE=`date +%d/%m/%Y\ %H:%M:%S` && echo $DATE`

to get the date but I don't know how or even if it could be possible to run this command after every command I execute on bash.

I would also be interested in running the same command before every command so I could know how long a command took.

Is it possible?

What file should I edit?

For example:

$ wget google.com
15/07/2017 23:40:05

I would be happy, if I could also introduce this following feauture:

$ wget google.com
15/07/2017 23:40:05 15/07/2017 23:40:11 
Program run for 00:00:06

where the first date is when I ran the program, second is when program terminated the third is self-explanatonary.

As you understood, I don't want to type every time

$ wget google.com && `DATE=`date +%d/%m/%Y\ %H:%M:%S` && echo $DATE`

Upvotes: 26

Views: 13949

Answers (5)

codeaprendiz
codeaprendiz

Reputation: 3195

I have the following alias in .zshrc which I find quite helpful and it achieves the requirement quite smoothly.

# Function to execute before each command with your command as argument
function preexec() {
    PREV_COMMAND=$1
    # echo "Prev command: $PREV_COMMAND"
    echo "\$ $PREV_COMMAND" | pbcopy
}

The following might be useful to get some context

Note: We are not using precmd here but might be useful in this context.

The preexec and precmd functions in Zsh are hooks that are invoked around the execution of a command line. They each serve different purposes:

  1. preexec: This function is executed just before any command line is executed. It's commonly used for things like starting timers, manipulating the command that's about to be run, or recording the command for later use.

  2. precmd: This function is executed before each prompt. It's often used for tasks that should be done before the user is prompted for the next command, such as printing information about the previous command, displaying Git branch information, or updating the title of the terminal.

To understand it better, think of the order of operations when you run a command in the terminal:

  • You type a command and hit enter.
  • The preexec function runs with your command as an argument.
  • Your command is executed.
  • The precmd function runs right before the next prompt is displayed.

The hooks give you an opportunity to run your own code at these specific points in the process. They're powerful tools for customizing your shell, and can be used to implement a wide variety of features.

Upvotes: 2

Marek Vitek
Marek Vitek

Reputation: 1633

To print timestamp after every command just modify your PS1 prompt and add date to it. The only catch here is that it will tell you time when command ended and new prompt showed. So in case you have your prompt open for long time just hit enter to capture start time before running your command.

PS1="\D{%F %T} \$ "

See this arch wiki page or just google bash prompt customization.

To add time spent executing program just add time before the command

$ time wget google.com

It will give you output like this

real 0m0.177s
user 0m0.156s
sys 0m0.020s

And you can get even more lazy and for commands that you dont't feel like typing time every time you run it, just create alias.

alias wget="time wget"

Because in bash aliases are run before other commands you can do it this way even if it looks like recursion. Then you will call it as you are used to.
And of course, aliases and prompt settings can be put in your .bashrc file, so you don't have to type them every time you open terminal.

Upvotes: 2

randomir
randomir

Reputation: 18687

You can add date/time to your prompt, via PS1 variable. You could use date command, but it's more efficient to use the supported special characters, like \d for date, or \D{strftime-fmt}.

For example:

PS1='\u@\h[\D{%F} \D{%T}]\w\$ '

or, with color:

PS1='\[\033[01;32m\]\u@\h\[\033[00m\][\[\033[02;33m\]\D{%F}\[\033[08m\]T\[\033[00m\]\[\033[02;33m\]\D{%T}\[\033[00m\]]\[\033[01;34m\]\w\[\033[00m\]\$ '

will show:

user@host[2017-07-16 00:01:17]~/somedir$

Note that in the second case (with color) we have a valid ISO8601 timestamp, with a "hidden" date/time separator T in the middle. If you select it with a mouse, T is visible and can be copied. (Also double-click will select the complete timestamp, not only date or time.)

Upvotes: 3

William Pursell
William Pursell

Reputation: 212228

To execute a cmd before every command entered, set a trap on DEBUG. Eg.

trap date DEBUG

To execute that command before emitting a prompt, set PROMPT_COMMAND:

PROMPT_COMMAND=date

Upvotes: 23

Petr Skocik
Petr Skocik

Reputation: 60058

This does exactly that:

PROMPT_COMMAND+=$'\n'"date +%d/%m/%Y\ %H:%M:%S"

The string in PROMPT_COMMAND gets evaluated after every command. You just need to add the date command to whatever you already had in it. ($'\n' (newline) is a somewhat more robust joiner than ; as two consecutive ; would give you a syntax error)

Upvotes: 7

Related Questions