documentation updates for history builtin to note it does not truncate the history file; documentation updates for HISTFILESIZE noting that it can work on lines or history entries depending on $HISTTIMEFORMAT; documentation update for history saving behavior at shell exit; history -w and history -a should update the number of history entries in the current session if they are using $HISTFILE; history -r now updates the number of history entries in the current session; improvement to history_truncate_file so it leaves fewer partial history entries when operating on lines

This commit is contained in:
Chet Ramey
2026-08-28 15:35:54 -04:00
parent 71327ab3b5
commit 81ddb6474b
16 changed files with 2086 additions and 1840 deletions
+34 -7
View File
@@ -85,8 +85,26 @@ by reading history entries from the
file named by the @env{HISTFILE} variable (default @file{~/.bash_history}).
This is referred to as the @dfn{history file}.
The history file is truncated, if necessary,
to contain no more than the number of history entries
to contain no more than the number of lines or history entries
specified by the value of the @env{HISTFILESIZE} variable.
The value of @env{HISTFILESIZE}
is interpreted as lines or possibly multi-line history
entries depending on whether the @env{HISTTIMEFORMAT}
variable has a value,
since that controls whether or not timestamps are written
to the history file.
If @env{HISTTIMEFORMAT}
has a value,
@env{HISTFILESIZE}
is interpreted as a number of
history entries, including timestamps.
If it does not, @env{HISTFILESIZE}
is interpreted as a number of lines,
which may result in incomplete history entries in the history file,
or the history file containing more lines than this maximum
to avoid leaving partial history entries.
If @env{HISTFILESIZE} is unset, or set to null, a non-numeric value,
or a numeric value less than zero, the history file is not truncated.
@@ -98,17 +116,26 @@ These timestamps are optionally displayed depending on the value of the
When present, history timestamps delimit history entries, making
multi-line entries possible.
When a shell with history enabled exits, Bash copies the last
@env{$HISTSIZE} entries from the history list to the file
named by @env{$HISTFILE}.
When a shell with history enabled exits, Bash
copies up to the last
@env{$HISTSIZE}
entries from the history list
to the file named by
@env{$HISTFILE}.
If the @code{histappend} shell option is set (@pxref{Bash Builtins}),
Bash appends the entries to the history file,
otherwise it overwrites the history file.
or if the number of history entries entered
during the current shell session is less than
@env{$HISTSIZE},
Bash appends the history entries entered during the current session
to @env{$HISTFILE}.
If @code{histappend} is not set, and the number of entries from the current
shell session exceeds @env{$HISTSIZE},
it overwrites the history file with the entries from the current session.
If @env{HISTFILE} is unset or null,
or if the history file is unwritable, the history is not saved.
After saving the history, Bash truncates the history file
to contain no more than @env{$HISTFILESIZE}
lines as described above.
entries as described above.
If the @env{HISTTIMEFORMAT}
variable is set, the shell writes the timestamp information
+8
View File
@@ -613,6 +613,7 @@ history_truncate_file (const char *fname, int lines)
{
char *buffer, *filename, *tempname, *bp, *bp1; /* bp1 == bp+1 */
int file, chars_read, rv, orig_lines, exists, r;
int has_timestamps;
struct stat finfo, nfinfo;
size_t file_size;
@@ -695,6 +696,11 @@ history_truncate_file (const char *fname, int lines)
}
buffer[chars_read] = '\0'; /* for the initial check of bp1[1] */
/* use a heuristic like in read_history_range() to determine whether the
file has timestamps, but don't change the comment character so
HIST_TIMESTAMP_START doesn't return true */
has_timestamps = history_comment_char == '\0' && buffer[0] == '#' && isdigit ((unsigned char)buffer[1]);
/* Count backwards from the end of buffer until we have passed
LINES lines. bp1 is set funny initially. But since bp[1] can't
be a comment character (since it's off the end) and *bp can't be
@@ -703,6 +709,8 @@ history_truncate_file (const char *fname, int lines)
because we decrement it one extra time the first time through the loop
and we need the final timestamp line. */
lines += history_write_timestamps;
if (history_write_timestamps == 0)
lines += has_timestamps; /* do our best */
for (bp1 = bp = buffer + chars_read - 1; lines > 0 && bp > buffer; bp--)
{
if (*bp == '\n' && HIST_TIMESTAMP_START(bp1) == 0)