Làm thế nào để xóa lịch sử của 10 lệnh cuối cùng trong shell?


131

Các lệnh sau

  511  clear
  512  history
  513  history -d 505
  514  history
  515  history -d 507 510 513
  516  history
  517  history -d 509
  518  history
  519  history -d 511
  520  history

Tôi có thể xóa từng lệnh một history -d 511, nhưng làm cách nào để xóa 10 lệnh cuối cùng và trong khoảng 10 lịch sử lệnh bằng lệnh đơn trong shell?

Chúng ta có thể viết một tập lệnh bash và thực thi để xóa lịch sử không?


18
vi $HISTFILEvà xóa những gì bạn muốn. Sử dụng head -n -10nếu bạn phải tự động hóa nó.
Anton Kovalenko

Là câu hỏi ngoài chủ đề ? hoặc Đây không phải là nơi thích hợp để hỏi loại câu hỏi này? Nếu vậy, tôi nên hỏi câu hỏi này ở đâu, ý tôi là nơi trao đổi ngăn xếp?
Justin John

1
Các lệnh Shell hoạt động như nhau cho dù bạn đăng nhập cục bộ hay qua ssh.
Barmar

2
Unix và Linux StackExchange (unix.stackexchange.com) có lẽ là một địa điểm tốt hơn cho câu hỏi này. Nó lạc đề ở đây vì nó không liên quan chặt chẽ đến lập trình.
Dan Mould

4
Lập trình một kịch bản shell là giải pháp lý tưởng cho câu hỏi này, do đó nó cần được xem xét liên quan đến lập trình. Không đề cập đến thực tế là OP thực sự yêu cầu cụ thể cho một kịch bản.
SSH này vào

Câu trả lời:


109

Bạn đã thử chỉnh sửa tệp lịch sử trực tiếp chưa:

~/.bash_history

2
@WherethereisaWill OP muốn có một kịch bản, không phải là cắm và chug thủ công.
Tyler Jandreau

10
sẽ có hiệu lực sau khi khởi chạy lại (đóng và mở lại) thiết bị đầu cuối
khaled_webdev

8
Nếu bạn làm điều này với vim, bạn có thể tìm thấy lịch sử xóa của mình trong ~/.viminfo vì vậy hãy chắc chắn xóa nó!
ví von

5
đôi khi nó được giữ trong bộ nhớ và mọi chỉnh sửa thủ công sẽ không được duy trì sau lần đăng nhập tiếp theo ..
siêu anh hùng

5
@FizerKhan Ý tôi là những thay đổi được thực hiện .bash_historycó thể được ghi đè bằng những gì được giữ trong bộ nhớ. Tôi thấy giải pháp này hữu ích: superuser.com/a/384383/253543
siêu anh hùng

73

Câu trả lời của tôi dựa trên các câu trả lời trước đó, nhưng với việc bổ sung đảo ngược trình tự để các mục lịch sử bị xóa từ gần đây nhất đến gần đây nhất.

Nhận lịch sử hiện tại của bạn (điều chỉnh số lượng dòng bạn muốn xem):

history | tail -n 10

Điều này mang lại cho tôi một cái gì đó như

1003  25-04-2016 17:54:52 echo "Command 1"
1004  25-04-2016 17:54:54 echo "Command 2"
1005  25-04-2016 17:54:57 echo "Command 3"
1006  25-04-2016 17:54:59 echo "Command 4"
1007  25-04-2016 17:55:01 echo "Command 5"
1008  25-04-2016 17:55:03 echo "Command 6"
1009  25-04-2016 17:55:07 echo "Command 7"
1010  25-04-2016 17:55:09 echo "Command 8"
1011  25-04-2016 17:55:11 echo "Command 9"
1012  25-04-2016 17:55:14 echo "Command 10"

Chọn vị trí bắt đầu và kết thúc cho các mục bạn muốn xóa. Tôi sẽ xóa các mục 1006 đến 1008.

for h in $(seq 1006 1008); do history -d 1006; done

Điều này sẽ tạo ra history -dcác lệnh cho 1006, sau đó 1007 trở thành 1006 và 1006 bị xóa, sau đó 1008 (trở thành 1007) bây giờ là 1006 và bị xóa.

Nếu tôi cũng muốn xóa lệnh xóa lịch sử thì nó phức tạp hơn một chút vì bạn cần biết mục lịch sử tối đa hiện tại.

Bạn có thể có được điều này với (có thể có một cách tốt hơn):

history 1 | awk '{print $1}'

Đặt nó lại với nhau, bạn có thể sử dụng điều này để xóa một phạm vi và cũng xóa lệnh xóa lịch sử:

for h in $(seq 1006 1008); do history -d 1006; done; history -d $(history 1 | awk '{print $1}')

Gói tất cả trong một chức năng để thêm vào ~/.bashrc :

histdel(){
  for h in $(seq $1 $2); do
    history -d $1
  done
  history -d $(history 1 | awk '{print $1}')
  }

Ví dụ xóa lệnh 4, 5 và 6 (1049-1051) và ẩn bằng chứng:

[18:21:02 jonathag@gb-slo-svb-0221 ~]$ history 11
 1046  25-04-2016 18:20:47 echo "Command 1"
 1047  25-04-2016 18:20:48 echo "Command 2"
 1048  25-04-2016 18:20:50 echo "Command 3"
 1049  25-04-2016 18:20:51 echo "Command 4"
 1050  25-04-2016 18:20:53 echo "Command 5"
 1051  25-04-2016 18:20:54 echo "Command 6"
 1052  25-04-2016 18:20:56 echo "Command 7"
 1053  25-04-2016 18:20:57 echo "Command 8"
 1054  25-04-2016 18:21:00 echo "Command 9"
 1055  25-04-2016 18:21:02 echo "Command 10"
 1056  25-04-2016 18:21:07 history 11
[18:21:07 jonathag@gb-slo-svb-0221 ~]$ histdel 1049 1051
[18:21:23 jonathag@gb-slo-svb-0221 ~]$ history 8
 1046  25-04-2016 18:20:47 echo "Command 1"
 1047  25-04-2016 18:20:48 echo "Command 2"
 1048  25-04-2016 18:20:50 echo "Command 3"
 1049  25-04-2016 18:20:56 echo "Command 7"
 1050  25-04-2016 18:20:57 echo "Command 8"
 1051  25-04-2016 18:21:00 echo "Command 9"
 1052  25-04-2016 18:21:02 echo "Command 10"
 1053  25-04-2016 18:21:07 history 11

Câu hỏi thực sự là xóa 10 lệnh cuối cùng khỏi lịch sử, vì vậy nếu bạn muốn tiết kiệm một chút nỗ lực, bạn có thể sử dụng một hàm khác để gọi histdelhàm thực hiện các phép tính cho bạn.

histdeln(){

  # Get the current history number
  n=$(history 1 | awk '{print $1}')

  # Call histdel with the appropriate range
  histdel $(( $n - $1 )) $(( $n - 1 ))
  }

Hàm này mất 1 đối số, số mục lịch sử trước đó cần xóa. Vì vậy, để xóa 10 lệnh cuối cùng khỏi lịch sử chỉ cần sử dụng histdeln 10.


history | tail -1 | awk '{print $1}'có thể được đơn giản hóa thànhhistory 1 | awk '{print $1}'
George Hilliard

-bash: tac: command not foundtrên Mac OSX, nếu không đây sẽ là câu trả lời tốt nhất.
Zim

for h in $(seq 1006 1008); do history -d 1006; donecái này hoạt động trong Ubuntu 16.04
mahfuz

Ngắn nhưng ngọt ngào:for i in {1..10}; do history -d $(($HISTCMD-11)); done
giả kim

30
for x in `seq $1 $2`
do
  history -d $1
done

3
Hãy chắc chắn sử dụng số cao hơn cho đối số đầu tiên hoặc bạn sẽ xóa mọi lệnh khác. Ví dụ: khi lệnh 511 bị xóa, mọi thứ sẽ thay đổi để 512 trở thành 511 mới và 513 là 512 mới. Do đó, history -d 511hoạt động như mong đợi, sau đó history -d 512xóa những gì từng là 513 và 512 vẫn còn trong lịch sử như lệnh 511. Hy vọng điều đó có ý nghĩa .
Matthew

5
@Matthew Điều đó không cần thiết. Tôi không xóa $xmỗi lần qua vòng lặp, tôi đang xóa $1. Vì vậy, đầu tiên nó xóa 511 và 512 trở thành 511. Sau đó, nó lại xóa 511, v.v.
Barmar

@Matthew Lưu ý rằng tôi đã nhận xét tương tự câu trả lời của Tyler. Tôi đã đưa ra giải pháp của mình như là một sửa chữa cho điều đó.
Barmar

bạn đã đúng, trong sự vội vàng của tôi khi viết nó thành một dòng trong dấu nhắc bash tôi đã sử dụng for i in... history -d $ivà nhận được kết quả mà tôi đã mô tả trong nhận xét của tôi ở trên. Sử dụng $ 1 điều này hoàn toàn chính xác như được nêu trong câu trả lời ban đầu của bạn.
Matthew

18

Đầu tiên, nhập: historyvà ghi lại chuỗi số dòng bạn muốn xóa.

Để xóa các dòng từ giả sử dòng 1800 đến 1815, hãy viết như sau trong terminal:

$ for line in $(seq 1800 1815) ; do history -d 1800; done

Nếu bạn muốn xóa lịch sử cho lệnh xóa, hãy thêm +1 cho 1815 = 1816 và lịch sử cho chuỗi đó + lệnh xóa sẽ bị xóa.

Ví dụ :

$ for line in $(seq 1800 1816) ; do history -d 1800; done

Tôi đã thực hiện cập nhật nhưng vẫn không hoạt động chính xác trong Ubuntu 12.04 .. :( Có vẻ như phần số dòng không hoạt động chính xác
Binod Kalathil

Tôi đã từ chối đề xuất chỉnh sửa của Binod vì đó không phải là lỗi logic. Mã ban đầu của Ghassan sử dụng cách tiếp cận tương tự như câu trả lời của Barmar - hoạt động. Các ý kiến ​​cho câu trả lời của Barmar giải thích lý do tại sao đề xuất thay thế 1800 bằng $linexóa mọi dòng khác và sau đó vượt quá phạm vi mong muốn.
Anthony Geoghegan

18

Với Bash 5, giờ bạn có thể thực hiện một phạm vi ... Hoan hô!:

history -d 511-520

hoặc đếm ngược 10:

history -d -10--1

Trích từ trang Bash 5 Man :

'lịch sử'

Tùy chọn, nếu được cung cấp, có các ý nghĩa sau:

'-d OFFSET' Xóa mục lịch sử tại vị trí OFFSET. Nếu OFFSET là dương, nó sẽ được chỉ định khi nó xuất hiện khi lịch sử được hiển thị. Nếu OFFSET âm tính, nó được hiểu là tương đối so với vị trí lịch sử cuối cùng, do đó, các chỉ số phủ định sẽ đếm ngược từ cuối lịch sử và chỉ số '-1' đề cập đến lệnh 'history -d' hiện tại.

'-d START-END' Xóa các mục lịch sử giữa các vị trí START và END, đã bao gồm. Giá trị dương và âm cho START và END được diễn giải như mô tả ở trên.

Đây là giải pháp của tôi cho Bash 4. Nó lặp đi lặp lại xóa một mục hoặc một phạm vi lịch sử bắt đầu với chỉ số thấp nhất.

delHistory () {
    count=$(( ${2:-$1} - $1 ))
    while [[ $count -ge 0 ]]; do
        history -d "$1"
        ((count--))
    done
}

delHistory 511 520


9

biên tập:

Thay đổi các vòng lặp giằng, gọi tốt. Ngoài ra, gọi hàm này với một trình vòng lặp ngược.

Bạn có thể có thể làm một cái gì đó như thế này:

#!/bin/bash
HISTFILE=~/.bash_history   # if you are running it in a 
                           # non interactive shell history would not work else
set -o history
for i in `seq $1 $2`;
do
    history -d $i
done
history -w

Nơi bạn sẽ gợi lên như thế này:

./nameOfYourScript 563 514

Lưu ý rằng tôi đã không đặt bất kỳ lỗi nào trong việc kiểm tra giới hạn. Tôi sẽ để nó như một bài tập cho người đọc.

xem thêm câu hỏi này


6
Sau khi bạn xóa 510, 511 trở thành 510, 512 trở thành 511, v.v. Vì vậy, điều này sẽ xóa mọi dòng khác.
Barmar

Bạn không thể bao gồm các biến trong mở rộng cú đúp.
chepner

seq 563 514sẽ không in gì cả. Bạn cần seq 563 -1 514. Thay phiên, bạn chỉ có thể sử dụng history -d $1với các đối số như514 563
anishsane

9

Có lẽ sẽ hữu ích cho một ai đó.
Khi bạn đăng nhập vào bất kỳ người dùng nào trong bất kỳ lịch sử bảng điều khiển / thiết bị đầu cuối nào của phiên hiện tại của bạn chỉ tồn tại trong một số "bộ đệm" sẽ chuyển sang ~ / .bash_history khi đăng xuất.
Vì vậy, để giữ bí mật, bạn chỉ có thể:
history -r && exit
và bạn sẽ được đăng xuất với tất cả lịch sử (và duy nhất) của phiên đã bị xóa;)


5

Tôi đã sử dụng kết hợp các giải pháp được chia sẻ trong luồng này để xóa dấu vết trong lịch sử lệnh. Đầu tiên, tôi xác minh nơi lưu lịch sử lệnh với:

echo $HISTFILE

Tôi đã chỉnh sửa lịch sử với:

vi <pathToFile>

Sau đó, tôi xóa bộ đệm lịch sử phiên hiện tại với:

history -r && exit

Lần tới khi bạn vào phiên này, lệnh cuối cùng mà bạn sẽ thấy trong lịch sử lệnh là lệnh cuối cùng mà bạn để lại trên pathToFile .


Điều này hiệu quả với tôi, đối với câu trả lời từ @jgc, khi tôi đăng nhập lại vào máy chủ, lịch sử đã quay trở lại, chỉ hoạt động cho phiên đăng nhập đó
Yogeshwar Tanwar


1

để xóa 10 mục cuối (dựa trên ví dụ của bạn):

history -d 511 520

1
Trong GNU bash, phiên bản 4.3.11 (1), điều này chỉ xóa dòng đầu tiên trong danh sách
Gary

1

Tôi sử dụng tập lệnh này để xóa 10 lệnh cuối cùng trong lịch sử:

pos=$HISTCMD; start=$(( $pos-11 )); end=$(( $pos-1 )); for i in $(eval echo "{${start}..${end}}"); do history -d $start; done

Nó sử dụng $HISTCMDvar môi trường để lấy chỉ mục lịch sử và sử dụng nó để xóa 10 mục cuối cùng trong history.


1

Hãy thử như sau:

for i in {511..520}; do history -d $i; echo "history -d $i"; done

Điều đó giả định rằng anh ta đã liệt kê lịch sử và biết trước tất cả các ID
Markoorn

và nó không thể là cái cuối cùng trong danh sách lịch sử, nếu không: "vị trí lịch sử nằm ngoài phạm vi"
devwebcl

nó phải là:for i in {511..520}; do history -d $i; echo "history -d 511"; done
devwebcl

1

Tôi sử dụng cái này (tôi có bash 4):

histrm() {
    local num=${1:- 1}
    builtin history -d $(builtin history | sed -rn '$s/^[^[:digit:]]+([[:digit:]]+)[^[:digit:]].*$/\1/p')
    (( num-- )) && $FUNCNAME $num
    builtin history -w
}

Các builtin historyphần cũng như phần cuối cùng -wlà do tôi có một biến thể của các thủ thuật nổi tiếng để chia sẻ lịch sử trên các thiết bị đầu cuối và chức năng này sẽ bị phá vỡ nếu không có các phần đó. Họ đảm bảo một cuộc gọi đến bash thực sựhistory nội dung (chứ không phải cho trình bao bọc của riêng tôi xung quanh nó) và để viết lịch sử vào HISTFILE ngay sau khi các mục nhập bị xóa.

Tuy nhiên, điều này sẽ hoạt động như với cấu hình lịch sử "bình thường".

Bạn nên gọi nó với số lượng mục cuối cùng bạn muốn xóa, ví dụ:

histrm 10

Sẽ loại bỏ 10 mục cuối cùng.


1
history -d 511;history -d 511;history -d 511;history -d 511;history -d 511;history -d 511;history -d 511;history -d 511;history -d 511;history -d 511;

Brute nhưng chức năng


0
for h in $(seq $(history | tail -1 | awk '{print $1-N}')  $(history | tail -1 | awk '{print $1}') | tac); do history -d $h; done; history -d $(history | tail -1 | awk '{print $1}')

Nếu bạn muốn xóa 10 dòng thì chỉ cần thay đổi giá trị của N thành 10.


0

Một hàm đơn giản có thể giết tất cả theo số (mặc dù nó bị lỗi)

kill_hist() {
    for i in $(echo $@ | sed -e 's/ /\n/g;' | sort -rn | sed -e 's/\n/ /;')
    do
            history -d $i;
    done
}
kill_hist `seq 511 520`
# or kill a few ranges
kill_hist `seq 1001 1010` `seq 1200 1201`

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.