.local/bin:filterHistory: Fix bug and refactor
Fix bug that `cut` only took the second field when splitting on ';' instead of everything after the first semicolon and thus not properly handling commands that contain semicolons. Add die() and hist-sort(). Use here-string instead of process substitution with input redirection. Rephrase comment.
This commit is contained in:
@@ -8,25 +8,32 @@
|
|||||||
## format of zshs extended history.
|
## format of zshs extended history.
|
||||||
## An automatic backup is created before deleting that can be used for recovery.
|
## An automatic backup is created before deleting that can be used for recovery.
|
||||||
|
|
||||||
[[ $# -eq 1 ]] || { echo "Specify history file" >&2; exit 1; }
|
die() {
|
||||||
[[ -e "$1" ]] || { echo "File does not exist" >&2; exit 1; }
|
printf "$1" >&2
|
||||||
[[ "$(stat -c '%a' "$1")" = "600" ]] || { echo "File does not look like a history file" >&2; exit 1; }
|
exit ${2:-1}
|
||||||
|
}
|
||||||
|
|
||||||
# Sort the commands per number of occurrences
|
[[ $# -eq 1 ]] || die "Specify a history file.\n"
|
||||||
most_used="$(\
|
[[ -e "$1" ]] || die "File does not exist.\n"
|
||||||
cut -d';' -f2 "$1" \
|
[[ "$(stat -c '%a' "$1")" = "600" ]] || die "File permissions are off.\n"
|
||||||
|
|
||||||
|
# Take a history file per stdin and sort the commands per number of occurrences
|
||||||
|
hist-sort() {
|
||||||
|
cut -d';' -f2- \
|
||||||
| sort \
|
| sort \
|
||||||
| uniq -c \
|
| uniq -c \
|
||||||
| sort -nr \
|
| sort -nr
|
||||||
)"
|
}
|
||||||
|
|
||||||
|
most_used="$(hist-sort <"$1")"
|
||||||
|
|
||||||
declare -a commands
|
declare -a commands
|
||||||
if command -v fzf >/dev/null 2>&1; then
|
if command -v fzf >/dev/null 2>&1; then
|
||||||
# Let the user pick in fzf from the most used commands
|
# Let the user pick in fzf from the most used commands
|
||||||
readarray -t commands < <(\
|
readarray -t commands <<<"$(
|
||||||
fzf -m --reverse --height 50% <<<"$most_used" \
|
fzf -m --reverse --height 50% <<<"$most_used" \
|
||||||
| sed -E 's/^[ \t]*[0-9]+ //' \
|
| sed -E 's/^[ \t]*[0-9]+ //'
|
||||||
)
|
)"
|
||||||
else
|
else
|
||||||
echo "Most used commands:"
|
echo "Most used commands:"
|
||||||
offset="$(head -1 <<<"$most_used" | sed -E 's/^( *[0-9]+).*$/\1/' | wc -m)"
|
offset="$(head -1 <<<"$most_used" | sed -E 's/^( *[0-9]+).*$/\1/' | wc -m)"
|
||||||
@@ -46,7 +53,7 @@ fi
|
|||||||
printf '%s\n' "${commands[@]}" | column -x
|
printf '%s\n' "${commands[@]}" | column -x
|
||||||
echo "Please confirm the deletion of these commands in $1 ('yes')"
|
echo "Please confirm the deletion of these commands in $1 ('yes')"
|
||||||
read yn
|
read yn
|
||||||
[[ "$yn" = "yes" ]] || exit 1
|
[[ "$yn" = "yes" ]] || die
|
||||||
|
|
||||||
tempd="$(mktemp -d)"
|
tempd="$(mktemp -d)"
|
||||||
cp "$1" "$tempd/$(basename "$1")"
|
cp "$1" "$tempd/$(basename "$1")"
|
||||||
@@ -55,16 +62,15 @@ echo
|
|||||||
|
|
||||||
for c in "${commands[@]}"; do
|
for c in "${commands[@]}"; do
|
||||||
# Escape all characters that sed could misinterpret.
|
# Escape all characters that sed could misinterpret.
|
||||||
pattern="^: [0-9]+:[0-9]+;$(sed -E 's/[./?+|()*\\^$]|\[|\]/\\&/g' <<<"$c")\$"
|
pat="^: [0-9]+:[0-9]+;$(sed -E 's/[./?+|()*\\^$]|\[|\]/\\&/g' <<<"$c")\$"
|
||||||
# Find first occurrence of the command in the history file
|
# Find line number of first occurrence of the command in the history file
|
||||||
first="$(grep -Enm1 "$pattern" "$1" | cut -d: -f1)"
|
first="$(grep -Enm1 "$pat" "$1" | cut -d: -f1)"
|
||||||
|
|
||||||
# Delete all lines beginning from the line after the first occurrence that
|
# Delete all occurrences of the command except for the first one
|
||||||
# contain (exactly) the command.
|
sed -Ei "$((${first} + 1)),\$ { /$pat/d }" "$1"
|
||||||
sed -Ei "$((first + 1)),\$ { /$pattern/d }" "$1"
|
|
||||||
echo "$c deleted"
|
echo "$c deleted"
|
||||||
done
|
done
|
||||||
|
|
||||||
echo
|
echo
|
||||||
echo "Following commands were deleted:"
|
echo "Following commands were deleted:"
|
||||||
diff "$1" "$tempd/$(basename "$1")" | grep "^>" | cut -d\; -f 2 | sort | uniq -c | sort -nr
|
diff "$1" "$tempd/$(basename "$1")" | grep "^>" | hist-sort
|
||||||
|
|||||||
Reference in New Issue
Block a user