سؤال

I would like to do something like

history 2960-2966

with the expectation of this kind of output:

2960  2013-12-09 20:59:35 bundle update
2961  2013-12-09 21:00:08 git st
2962  2013-12-09 21:00:12 git add .
2963  2013-12-09 21:01:19 git st
2964  2013-12-09 21:01:43 git log
2965  2013-12-09 21:02:45 git st
2966  2013-12-09 21:02:57 git reset HEAD Gemfile.lock

Is this possible in the bash shell?

UPDATE: My question is about seeing those seven history rows, not the dates, per se; it just happens that I have a HISTTIMEFORMAT directive in my .bash_profile to give the date and time stamp. If I were to remove it then I would wish history 2960-2966, or something, to generate this output:

2960  bundle update
2961  git st
2962  git add .
2963  git st
2964  git log
2965  git st
2966  git reset HEAD Gemfile.lock

I want the desired history rows to be displayed, preferably with any customization I've specified in .bash_profile.

Why would I want this? A very simple use case is: I do something like history | grep 'bundle update' get a decent result, then want to see some history from that point plus a few lines farther along, or maybe the history bracketing that point.

هل كانت مفيدة؟

المحلول

You could use sed. Say:

history | sed -n '2960,2966p'

to print line numbers 2960 to 2966 from the output of history command.

Quoting help history:

If the $HISTTIMEFORMAT variable is set and not null, its value is used
as a format string for strftime(3) to print the time stamp associated
with each displayed history entry.  No time stamps are printed otherwise.

You could set the format to get the timestamp in the desired format by saying:

export HISTTIMEFORMAT="%F %T "

Since the history file is written by default only upon session close, you'd need to say:

history -w

in order to update the history file in the current session.

نصائح أخرى

fc -l 2960 2966

This works on OS 10.6.X. It gives exactly what you need. Hope this helps!

try the following command . this will display the range from 2960 to 2966

fc -ln 2960-2966

to execute them you can try this

eval "$(fc -ln 2960 2966)"

Hope this helps.

Tharanga Abeyseela

We want to display entries from start to end inclusive.

The $HISTCMD variable built into gives the number of the latest entry to the history buffer.
The history command takes an n parameter, which tells it to display the last n entries. So the start number when displaying entries with the n parameter would be:

start = $HISTCMD - n

Rearranging in terms of n we get this expression which can be passed to history:

n = $HISTCMD - start

Now we want to display only the entries from start to end inclusive, i.e. end - start + 1 entries. We can use head to give just those enties.

Wrapping this up into an easy-to-use function we have:

$ function histrange {
>     history $(($HISTCMD - $1)) | head -n$(($2 - $1 + 1))
> }
$ histrange 2097 2100
 2097  2013-12-15 21:54:02 man ls
 2098  2013-12-15 21:54:06 ls
 2099  2013-12-15 21:54:10 man df
 2100  2013-12-15 21:54:15 df -k .
$ 

Here's a way to do it with :

$ function histrange {
> history | grep -E -A $(($2 - $1)) "^[[:space:]]*$1[[:space:]]"
> }
$ histrange 2100 2105
 2100  2013-12-15 21:54:15 df -k .
 2101  2013-12-15 21:54:18 history
 2102  2013-12-15 21:54:40 histrange 2097 2100
 2103  2013-12-15 21:55:30 man grep
 2104  2013-12-15 22:35:33 man history
 2105  2013-12-15 22:38:35 export HISTTIMEFORMAT="%F %T "
$

We make sure the regular expression is anchored to the start of the line, has zero or more whitespace before the start number and one whitespace after the start number, so we only exactly match the start number to the history entry number and nothing else. We use the -A option to grep to display the $end - $start lines following the match.

Given what you say under why you want this,

history | grep -A 4 -B 3 whatyousearchfor

should give you just what you want.

The whatyousearchfor can either be your original serch term or you first do grep without context lines and then use the history line number as whatyousearchfor.

$> export HISTTIMEFORMAT="    %F    %T     "

then:

$> history | awk '{if (1070<=$1 && $1<=1075) {print}}'

This is almost the response of devnull. Never though to things like that before, but I liked the idea and think it will be usefull for me too. I get an approximative answer searching from the built-in bash help.

$> help history

...

If the $HISTTIMEFORMAT variable is set and not null, its value is used as a format string for strftime(3) to print the time stamp associated with each displayed history entry. No time stamps are printed otherwise.

then

$> man 3 srtftime
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top