Comment supprimer des commandes dans l'historique correspondant à une chaîne donnée?

13

Je dois supprimer toutes les commandes de mon historique correspondant à une chaîne. J'ai essayé:

$ history | grep searchstring | cut -d" " -f2 | history -d
-bash: history: -d: option requires an argument

$ history | grep searchstring | cut -d" " -f2 | xargs history -d
xargs: history: No such file or directory

$ temparg() { while read i; do "$@" "$i"; done }
$ history | grep searchstring | cut -d" " -f2 | temparg history -d
(no error, but nothing is deleted)

Quel est le bon moyen de le faire?

linuxfix
la source
Bien qu'il existe des réponses utiles ci-dessous, je me demande toujours pourquoi cela ne fonctionne pas history -d X. Je suis tombé sur cette question parce que je venais de le faire history | grep search_str | sort -nr | awk '{print $1}' | while read i; do history -d $i; done. Aucune erreur, mais rien n'a été supprimé. Quelqu'un peut-il expliquer pourquoi?
mivk

Réponses:

18

La historycommande fonctionne uniquement sur votre fichier d'historique $HISTFILE(généralement ~/.historyou ~/.bash_history). Ce sera beaucoup plus facile si vous supprimez simplement les lignes de ce fichier, ce qui peut être fait de plusieurs façons. grepest une façon, mais vous devez faire attention à ne pas écraser le fichier tout en le lisant:

$ grep -v searchstring "$HISTFILE" > /tmp/history
$ mv /tmp/history "$HISTFILE"

Une autre façon consiste à sed:

$ sed -i '/searchstring/d' "$HISTFILE"
Michael Mrozek
la source
Bonne réponse; $HISTFILEpourrait contenir des espaces, probablement la peine de le citer.
Chris Down
Attention ... l'histfile est imprévisible, si vous avez de nombreux shells ouverts, cela ne dit pas exactement ce qui sera sauvegardé et dans quel ordre. Quelqu'un peut-il confirmer que les shells déjà ouverts ne réécriront pas l'historique qu'ils ont chargé lors de l'initialisation, une fois fermés?
orion
8

La réponse de Michael Mrozek fonctionnera si vous ne vous souciez pas de supprimer des commandes de la session en cours. Si vous le faites, vous devez écrire dans le fichier historique avant de faire les opérations de son message en faisant history -a.

De plus, après avoir supprimé les entrées souhaitées de votre fichier d'historique, vous pouvez le recharger en émettant history -c, puis history -r.

Chris Down
la source
2

Sur la base des réponses de Michael et Chris , j'ai trouvé ce qui suit. Ajoutez-le à votre ~/.bashrcfichier, puis chargez-le avec . ~/.bashrcou source ~/.bashrc.

:<<COMMENT
    Deletes all lines from the history that match a search string, with a
    prompt. The history file is then reloaded into memory.

    Examples
        hxf "rm -rf"
        hxf ^source

    See:
    - https://unix.stackexchange.com/questions/57924/how-to-delete-commands-in-history-matching-a-given-string
COMMENT
#The unalias prevents odd errors when calling". ~/.bashrc" (May result in
#"not found" errors. That's okay).
unalias hxf
hxf()  {
    read -r -p "About to delete all items from history that match \"$1\". Are you sure? [y/N] " response
    response=${response,,}    # tolower
    if [[ $response =~ ^(yes|y)$ ]]
    then
        #Delete all matched items from the file, and duplicate it to a temp
        #location.
        echo -e "grep -v \"$1\" \"$HISTFILE\" > /tmp/history"
        grep -v "$1" "$HISTFILE" > /tmp/history

        #Clear all items in the current sessions history (in memory). This
        #empties out $HISTFILE.
        echo "history -c"
        history -c

        #Overwrite the actual history file with the temp one.
        echo -e "mv /tmp/history \"$HISTFILE\""
        mv /tmp/history "$HISTFILE"

        #Now reload it.
        echo -e "history -r \"$HISTFILE\""
        history -r "$HISTFILE"     #Alternative: exec bash
    else
        echo "Cancelled."
    fi
}
aliteralmind
la source
2

Pour ceux qui recherchent une doublure:

while history -d $(history | grep 'SEARCH_STRING_GOES_HERE'| head -n 1 | awk {'print $1'}) ; do :; history -w; done

Donc, si vous voulez par exemple. supprimez plusieurs lignes contenant un mot de passe, remplacez simplement "SEARCH_STRING_GOES_HERE" par le mot de passe. Cela recherchera toute votre histoire pour cette chaîne de recherche et la supprimera.

2 choses à savoir

  • grep utilise regex sauf si vous fournissez -F comme argument
  • La commande affichera 1 erreur, une fois qu'il n'y aura plus de correspondance. Ignorez-le.
thelogix
la source
J'ai une erreur (-bash: history: -d: l'option nécessite un argument), mais cela a quand même fonctionné?
paradroid
Il exécute la commande delete en continu, jusqu'à ce qu'il échoue avec une erreur (car il n'y a plus rien à supprimer). Ignorez simplement l'erreur.
thelogix
1
cat "$HISTFILE" | grep -v "commandToDelete" >> "$HISTFILE" && exit

Cela a fonctionné pour moi. history -c && history -a n'a pas rechargé le fichier d'historique correctement pour moi. Au lieu de cela, je quitte simplement ma session juste après avoir réécrit le fichier historique afin que celui en mémoire ne le remplace pas.

Hydde87
la source