6
\$\begingroup\$

In effort to be more effective and productive with terminals I have started building a bash script. It is for handling the bash history of concurrently running terminals, archiving old commands, and dynamically loading bash history profiles.

Most current development is going to be found at https://launchpad.net/bashory

First part is making the history dynamic and portable. I do this with 2 source files.

~./bashory/bashory

###
# Merging yesterday with today if recent.
# Vars need to be set could be converted to weeks or months or whatever.
bthen=$(date +%F --date="6 hours ago")
bnow=$(date +%F)
blater(){
date +%F
}
###

###
# Set history location based on day, but could esaily be changed to week or month.
bashHistory=~/.bashory/archive/$bnow.bash_history
###

###
# need to make sure a file exists right away.
touch $bashHistory
###

### doubles $HISTFILE contents
# The if statement could be removed for always or never load yesterday.
# Better yet changed to a flagable option.
#
# Yesterday is so long ago only load todays history minus 1 which gets loaded with bashory()
# Since yesterday was recent lets make sure a file exists for then
# Now only load yesterdays history
# Then add todays minus 1 which gets loaded with bashory2()
if [ $bnow = $bthen ]; then
    cat  $bashHistory > $HISTFILE
else
    touch ~/.bashory/archive/$bthen.bash_history
    cat ~/.bashory/archive/$bthen.bash_history > $HISTFILE
    cat  $bashHistory >> $HISTFILE
fi
###

. ~/.bashory/bastory.bashory

And ~/.bashory/bastory.bashory

###
# This file is seperated to make sure 
# These function are correct during profile switching
###

###
# Ensure verify is turned back on
shopt -s histverify
###

###
# Main action is here. 
# 
# Reset var just in case it's tomorrow 
# Just in case if it is tomorrow make sure the file exisits
# Append new command
# Add that same command to the current history
# Clear loaded histroy
# Reload new history 
bashory(){
    bashHistory=~/.bashory/archive/$(blater).bash_history
    touch $bashHistory
    history -a $bashHistory
    tail -n1 $bashHistory >> $HISTFILE
    history -cr $HISTFILE
}
###

###
# Complete change of bastory 
# Rather than load only a history profile it will source another script
# The other script will load the required history and any other needs
# consideration of how the profile unloads is important
# This will always be done by calling bashory() from a sourced ~/.bashory/profiles/profile.bash_history
# 
# 
bastory() {
    if [ -f ~/.bashory/profiles/$1.bastory ]; then
    . ~/.bashory/profiles/$1.bastory
    else
        echo no profile found at
        echo "~/.bashory/profiles/$1.bastory"
        echo reverting back to bashory
        bashory
    fi
}
###

###
# Load it on the prompt
export PROMPT_COMMAND="bashory"
###

Then the second part is a basic profile made of upto 3 parts. the .bashory/profiles/sample.bastory

sample="Sample"
sampleHistory=0

sample(){
        history -a $bashHistory
        tail -n1 $bashHistory >> $HISTFILE
        history -cr $HISTFILE
}



bastory(){

    history -a $bashHistory

    if [ -f ~/.bash/sample.bash_history ]; then
        bashHistory=~/.bashory/profiles/sample.bash_history
        history -a $bashHistory
        tail -n1 $bashHistory >> $HISTFILE
        history -cr $HISTFILE
    else
        bashHistory=~/.bashory/profiles/sample.bash_history
        sampleHistory=1
        cat << 'EOF' > $bashHistory
mount /cdrom
mount /dvd
umount /dvd
umount /dvd

EOF
        cat $bashHistory > $HISTFILE
        history -cr $HISTFILE
    fi
    export PROMPT_COMMAND="sample"
}

bashory() {
    . ~/.bashory/profiles/sample.bashory
}

then the ~/.bashory/profiles/sample.bashory

unset sample
unset $sample
if [ "$sampleHistory" = 1 ]; then 
    echo "sampled without sample.bash_history so deleting it now"
    rm $bashHistory
else
    echo "sampled with sample.bash_history"
fi

echo reverting to normal
. ~/.bashory/bastory.bashory

And optionally the ~/.bashory/profiles/sample.bash_history

# As Example of basic common task (ie !1, !2, !3, !4)
mount /cdrom
umount /cdrom
mount /dvd
umount /dvd    
\$\endgroup\$
0

1 Answer 1

4
\$\begingroup\$

First of all, you've got to give different names to bashory and bastory... I was very confused while reading the code, at first I thought it was a typo, it took me a while to realize they are different things. To avoid confusion, it would be better to give them distinctly different names.


In many places you use the cat command to overwrite files, like this:

cat $bashHistory > $HISTFILE

While this certainly works, if you want to copy a file use the cp command, as it's designed for that. Using cp might have another advantage, you could add the -v flag to make the operation verbose, which can be useful, if you're interested in that.


Sometimes you use somewhat long paths multiple times, for example ~/.bashory/profiles/$1.bastory in here:

bastory() {
    if [ -f ~/.bashory/profiles/$1.bastory ]; then
        . ~/.bashory/profiles/$1.bastory
    else
        echo no profile found at
        echo "~/.bashory/profiles/$1.bastory"
        echo reverting back to bashory
        bashory
    fi
}

This is error prone, you might mistype one of the paths, which can be hard to notice and a nightmare to debug. Cache such long-ish paths in variables to make it safer and easier, for example:

bastory() {
    profile=~/.bashory/profiles/$1.bastory
    if [ -f $profile ]; then
        . $profile
    else
        echo no profile found at
        echo $profile
        echo reverting back to bashory
        bashory
    fi
}

You do this:

bashHistory=~/.bashory/archive/$bnow.bash_history
# need to make sure a file exists right away.
touch $bashHistory

Which will file unless the directory ~/.bashory/archive already exists. Have you done anything to ensure that? (It's not anywhere in your post.)

To make this more fault tolerant, you might want to do mkdir -p ~/.bashory/archive before the touch. And the same goes for ~/.bashory/profiles.


Just a wild guess, maybe you wanted to write this on a single line:

blater() { date +%F; }  # The trick is to put a ";" before the closing "}"
\$\endgroup\$
1
  • \$\begingroup\$ Appreciate the input I will make adjustments based on your suggestions. \$\endgroup\$
    – CrandellWS
    Aug 22, 2014 at 2:22

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.