จะลบประวัติ 10 คำสั่งล่าสุดในเชลล์ได้อย่างไร


131

คำสั่งดังต่อไปนี้

  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

ฉันสามารถลบทีhistory -d 511ละคำสั่ง แต่จะลบ 10 คำสั่งสุดท้ายและระหว่าง 10 คำสั่งประวัติโดยใช้คำสั่งเดียวในเชลล์ได้อย่างไร

เราสามารถเขียน bash script และดำเนินการลบประวัติได้หรือไม่?


18
vi $HISTFILEและลบสิ่งที่คุณต้องการ ใช้head -n -10หากคุณต้องทำให้เป็นอัตโนมัติ
Anton Kovalenko

คำถามนี้ไม่ตรงประเด็นหรือไม่? หรือนี่ไม่ใช่สถานที่ที่ควรถามคำถามประเภทนี้? ถ้าเป็นเช่นนั้นฉันควรถามคำถามนี้ฉันหมายถึงที่ไหนในการแลกเปลี่ยนสแต็ก
Justin John

1
คำสั่งเชลล์ทำงานเหมือนกันไม่ว่าคุณจะเข้าสู่ระบบในเครื่องหรือผ่าน ssh
Barmar

2
Unix และ Linux StackExchange (unix.stackexchange.com) น่าจะเป็นสถานที่ที่ดีกว่าสำหรับคำถามนี้ มันไม่เกี่ยวกับเรื่องนี้เพราะมันไม่ได้เกี่ยวข้องกับการเขียนโปรแกรมอย่างเคร่งครัด
แดนปั้น

4
การเขียนโปรแกรมเชลล์สคริปต์เป็นทางออกที่ดีสำหรับคำถามนี้ดังนั้นจึงควรพิจารณาว่าเกี่ยวข้องกับการเขียนโปรแกรม ไม่ต้องพูดถึงว่าจริงๆแล้ว OP ขอสคริปต์โดยเฉพาะ
SSH

คำตอบ:


109

คุณได้ลองแก้ไขไฟล์ประวัติโดยตรงหรือไม่:

~/.bash_history

2
@Wherethereisa จะ OP ต้องการสคริปต์ไม่ใช่ปลั๊กและตัวจับแบบแมนนวล
Tyler Jandreau

10
จะมีผลหลังจากเปิดใหม่ (ปิดและเปิดใหม่) เทอร์มินัล
khaled_webdev

8
หากคุณทำสิ่งนี้ด้วยกลุ่มคุณอาจพบประวัติการลบของคุณ~/.viminfoดังนั้นอย่าลืมลบออกด้วย!
waltwood

5
บางครั้งมันจะถูกเก็บไว้ในหน่วยความจำและการแก้ไขด้วยตนเองจะไม่ปรากฏหลังจากล็อกอินครั้งต่อไป ..
superhero

5
@FizerKhan ฉันหมายความว่าการเปลี่ยนแปลงที่เกิดขึ้น.bash_historyสามารถเขียนทับได้โดยสิ่งที่เก็บไว้ในความทรงจำ ฉันพบว่าโซลูชันนี้มีประโยชน์: superuser.com/a/384383/253543
superhero

73

คำตอบของฉันขึ้นอยู่กับคำตอบก่อนหน้านี้ แต่ด้วยการเพิ่มการย้อนกลับลำดับเพื่อให้รายการประวัติถูกลบจากล่าสุดไปหาน้อยที่สุด

รับประวัติปัจจุบันของคุณ (ปรับจำนวนบรรทัดที่คุณต้องการดู):

history | tail -n 10

สิ่งนี้ทำให้ฉันมีบางอย่างเช่น

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"

เลือกตำแหน่งเริ่มต้นและสิ้นสุดสำหรับรายการที่คุณต้องการลบ ฉันจะลบรายการ 1006 ถึง 1008

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

สิ่งนี้จะสร้างhistory -dคำสั่งสำหรับ 1006 จากนั้น 1007 กลายเป็น 1006 และ 1006 จะถูกลบจากนั้น 1008 (กลายเป็น 1007) จะเป็น 1006 และจะถูกลบ

หากฉันต้องการลบคำสั่งลบประวัติด้วยก็จะซับซ้อนกว่านี้เล็กน้อยเพราะคุณจำเป็นต้องรู้รายการประวัติสูงสุดในปัจจุบัน

คุณสามารถรับสิ่งนี้ได้ด้วย (อาจมีวิธีที่ดีกว่า):

history 1 | awk '{print $1}'

การรวมเข้าด้วยกันคุณสามารถใช้สิ่งนี้เพื่อลบช่วงและลบคำสั่งลบประวัติ:

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

รวมทั้งหมดนี้ไว้ในฟังก์ชันเพื่อเพิ่มใน~/.bashrc:

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

ตัวอย่างการลบคำสั่ง 4, 5 และ 6 (1049-1051) และซ่อนหลักฐาน:

[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

คำถามคือการลบคำสั่ง 10 คำสั่งสุดท้ายออกจากประวัติดังนั้นหากคุณต้องการประหยัดแรงคุณสามารถใช้ฟังก์ชันอื่นเพื่อเรียกใช้histdelฟังก์ชันที่คำนวณให้คุณได้

histdeln(){

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

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

ฟังก์ชันนี้รับ 1 อาร์กิวเมนต์จำนวนรายการประวัติก่อนหน้าที่จะลบ เพื่อที่จะลบเมื่อ 10 histdeln 10คำสั่งจากประวัติศาสตร์เพียงแค่การใช้งาน


history | tail -1 | awk '{print $1}'สามารถทำให้ง่ายขึ้นhistory 1 | awk '{print $1}'
George Hilliard

-bash: tac: command not foundบน Mac OSX มิฉะนั้นจะเป็นคำตอบที่ดีที่สุด
Zim

for h in $(seq 1006 1008); do history -d 1006; doneใช้งานได้ใน ubuntu 16.04
mahfuz

สั้น ๆ แต่ไพเราะ:for i in {1..10}; do history -d $(($HISTCMD-11)); done
alchemy

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

3
อย่าลืมใช้ตัวเลขที่สูงกว่าสำหรับอาร์กิวเมนต์แรกมิฉะนั้นคุณจะลบคำสั่งอื่น ๆ ทั้งหมด เช่นเมื่อลบคำสั่ง 511 ทุกอย่างจะเลื่อนลงดังนั้น 512 จึงกลายเป็น 511 ใหม่และ 513 เป็น 512 ใหม่ดังนั้นจึงhistory -d 511ทำงานได้ตามที่คาดไว้จากนั้นhistory -d 512ลบสิ่งที่เคยเป็น 513 และ 512 ยังคงอยู่ในประวัติเป็นคำสั่ง 511 หวังว่าจะสมเหตุสมผล .
Matthew

5
@ แมทธิวนั่นไม่จำเป็น ฉันไม่ได้ลบในแต่ละครั้งที่ผ่านห่วงฉันลบ$x $1ก่อนอื่นมันจะลบ 511 และ 512 กลายเป็น 511 จากนั้นลบ 511 อีกครั้งไปเรื่อย ๆ
Barmar

@ แมทธิวสังเกตว่าฉันแสดงความคิดเห็นคล้ายกับคำตอบของไทเลอร์ ฉันคิดวิธีแก้ปัญหาขึ้นมาเพื่อแก้ไขปัญหานั้น
Barmar

คุณพูดถูกต้องในความเร่งรีบของฉันเมื่อเขียนสิ่งนี้ในบรรทัดเดียวในพรอมต์ทุบตีของฉันฉันใช้for i in... history -d $iและได้ผลลัพธ์ที่ฉันอธิบายไว้ในความคิดเห็นด้านบน การใช้ $ 1 นี้ถูกต้องตามที่ระบุไว้ในคำตอบเดิมของคุณ
Matthew

19

ด้วย Bash 5 ตอนนี้คุณสามารถทำช่วง ... ไชโย!:

history -d 511-520

หรือนับถอยหลัง 10:

history -d -10--1

ข้อความที่ตัดตอนมาจากBash 5 Man Page :

'ประวัติศาสตร์'

ตัวเลือกหากมีให้มีความหมายดังต่อไปนี้:

'-d OFFSET' ลบรายการประวัติที่ตำแหน่ง OFFSET หาก OFFSET เป็นค่าบวกควรระบุตามที่ปรากฏเมื่อแสดงประวัติ ถ้า OFFSET เป็นค่าลบจะถูกตีความว่าสัมพันธ์กับตำแหน่งที่มากกว่าตำแหน่งสุดท้ายในประวัติดังนั้นดัชนีเชิงลบจะนับย้อนกลับจากจุดสิ้นสุดของประวัติและดัชนี '-1' หมายถึงคำสั่ง 'history -d' ปัจจุบัน

'-d START-END' ลบรายการประวัติระหว่างตำแหน่ง START และ END รวม ค่าบวกและลบสำหรับ START และ END ถูกตีความตามที่อธิบายไว้ข้างต้น

นี่คือวิธีแก้ปัญหาของฉันสำหรับ Bash 4 มันจะลบรายการเดียวหรือช่วงของประวัติที่เริ่มต้นด้วยดัชนีต่ำสุดซ้ำ ๆ

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

delHistory 511 520

18

ขั้นแรกพิมพ์: historyและเขียนลำดับของหมายเลขบรรทัดที่คุณต้องการลบ

หากต้องการล้างบรรทัดจากสมมติว่าบรรทัด 1800 ถึง 1815 ให้เขียนสิ่งต่อไปนี้ในเทอร์มินัล:

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

หากคุณต้องการลบประวัติสำหรับคำสั่งลบให้เพิ่ม +1 สำหรับ 1815 = 1816 และประวัติสำหรับลำดับนั้น + คำสั่งการลบจะถูกลบ

ตัวอย่างเช่น :

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

ฉันทำการอัปเดต แต่ยังทำงานไม่ถูกต้องใน Ubuntu 12.04 .. :( ดูเหมือนว่าส่วนหมายเลขบรรทัดทำงานไม่ถูกต้อง
Binod Kalathil

ฉันปฏิเสธการแก้ไขที่แนะนำของ Binod เนื่องจากไม่ใช่ข้อผิดพลาดทางตรรกะ รหัสดั้งเดิมของ Ghassan ใช้แนวทางเดียวกับคำตอบของ Barmar ซึ่งได้ผล ความคิดเห็นต่อคำตอบของ Barmar อธิบายว่าเหตุใดข้อเสนอแนะในการแทนที่ 1800 ด้วยการ$lineลบบรรทัดอื่น ๆ ทั้งหมดและเกินช่วงที่ต้องการ
Anthony Geoghegan


9

แก้ไข:

เปลี่ยนวงเล็บปีกกาโทรดี นอกจากนี้เรียกใช้ฟังก์ชันนี้ด้วยตัวย้อนกลับ

คุณอาจทำสิ่งนี้ได้:

#!/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

ที่คุณจะทำให้เกิดสิ่งนี้:

./nameOfYourScript 563 514

สังเกตว่าฉันไม่ได้ใส่ข้อผิดพลาดใด ๆ ในการตรวจสอบขอบเขต ฉันจะปล่อยให้มันเป็นแบบฝึกหัดสำหรับผู้อ่าน

ดูคำถามนี้ด้วย


6
หลังจากที่คุณลบ 510, 511 จะกลายเป็น 510, 512 กลายเป็น 511 และอื่น ๆ ดังนั้นนี่จะลบทุกบรรทัด
Barmar

คุณไม่สามารถรวมตัวแปรในการขยายวงเล็บปีกกา
chepner

seq 563 514จะไม่พิมพ์อะไรเลย seq 563 -1 514คุณจำเป็นต้อง หรือคุณสามารถใช้history -d $1กับอาร์กิวเมนต์ได้เช่น514 563
anishsane

9

อาจจะมีประโยชน์สำหรับใครบางคน
เมื่อคุณเข้าสู่ระบบผู้ใช้ใด ๆ ของคอนโซล / เทอร์มินัลประวัติของเซสชันปัจจุบันของคุณจะมีอยู่ใน "บัฟเฟอร์" บางส่วนเท่านั้นซึ่งจะล้างเป็น ~ / .bash_history ในการออกจากระบบของคุณ
ดังนั้นเพื่อรักษาความลับคุณสามารถทำได้:
history -r && exit
และคุณจะออกจากระบบโดยล้างประวัติเซสชันทั้งหมดของคุณ (และเท่านั้น);)


5

ฉันใช้ชุดของโซลูชันที่ใช้ร่วมกันในเธรดนี้เพื่อลบการติดตามในประวัติคำสั่ง ก่อนอื่นฉันตรวจสอบว่าบันทึกประวัติคำสั่งไว้ที่ไหนด้วย

echo $HISTFILE

ฉันแก้ไขประวัติด้วย:

vi <pathToFile>

หลังจากนั้นฉันจะล้างบัฟเฟอร์ประวัติเซสชันปัจจุบันด้วย:

history -r && exit

ครั้งต่อไปที่คุณป้อนเพื่อเซสชั่นนี้คำสั่งสุดท้ายที่คุณจะได้เห็นในประวัติคำสั่งเป็นครั้งสุดท้ายที่คุณทิ้งไว้บนpathToFile


สิ่งนี้ใช้ได้กับฉันสำหรับคำตอบจาก @jgc เมื่อฉันลงชื่อเข้าใช้เซิร์ฟเวอร์อีกครั้งประวัติจะกลับมาอีกครั้งใช้งานได้เฉพาะกับเซสชันที่เข้าสู่ระบบเท่านั้น
Yogeshwar Tanwar


1

เพื่อลบ 10 รายการสุดท้าย (ตามตัวอย่างของคุณ):

history -d 511 520

1
ใน GNU bash เวอร์ชัน 4.3.11 (1) จะลบบรรทัดแรกในรายการเท่านั้น
Gary

1

ฉันใช้สคริปต์นี้เพื่อลบคำสั่ง 10 คำสั่งสุดท้ายในประวัติ:

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

ใช้$HISTCMDvar สภาพแวดล้อมเพื่อรับดัชนีประวัติและใช้เพื่อลบ 10 รายการล่าสุดในhistory.


1

ลองทำดังต่อไปนี้:

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

ซึ่งถือว่าเขาได้ระบุประวัติไว้แล้วและรู้จัก ID ทั้งหมดล่วงหน้า
Markoorn

และไม่สามารถอยู่ในรายการประวัติล่าสุดได้มิฉะนั้น: "ตำแหน่งประวัติอยู่นอกช่วง"
devwebcl

ต้องเป็น:for i in {511..520}; do history -d $i; echo "history -d 511"; done
devwebcl

1

ฉันใช้สิ่งนี้ (ฉันมี 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
}

builtin historyชิ้นส่วนและส่วนสุดท้าย-wเป็นเพราะฉันได้จัดวางรูปแบบของเทคนิคที่มีชื่อเสียงในการแบ่งปันประวัติศาสตร์ข้ามเทอร์มินัลและฟังก์ชันนี้จะพังโดยไม่มีส่วนเหล่านั้น พวกเขามั่นใจว่าจะเรียกร้องให้ทุบตีจริงhistoryตัว (ไม่ใช่การห่อหุ้มของฉันเอง) และเขียนประวัติลงใน HISTFILE ทันทีหลังจากที่รายการถูกลบออก

อย่างไรก็ตามสิ่งนี้จะใช้งานได้เหมือนกับการกำหนดค่าประวัติ "ปกติ"

คุณควรเรียกมันด้วยจำนวนรายการสุดท้ายที่คุณต้องการลบเช่น:

histrm 10

จะลบ 10 รายการสุดท้าย


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;

ดุร้าย แต่ใช้งานได้


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}')

หากคุณต้องการลบ 10 บรรทัดให้เปลี่ยนค่าของ N เป็น 10


0

ฟังก์ชันง่ายๆสามารถฆ่าทั้งหมดตามจำนวน (แม้ว่าจะมีข้อผิดพลาดก็ตาม)

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`

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.