header

Useless bash features

I spent most of today reading first four parts of the classic GNU Bash Reference Manual and I thought I would share some of the useless things I found. It's supposed to be a "brief introduction" to features found in the Bash manual page, but I hate man pages, I just read this reference manual in its beautiful info form. It already lists every option of every builtin command, all the special parameters, the syntax, if I ever thought this info manual wasn't enough for something to do with Bash then I will need serious psychiatric help.

Change the command not found message

This is I think the most interesting one that I found. When you type a command and bash can't find it in $PATH after checking functions and shell builtins, we all know bash gives you the standard "command not found" error message. But you can actually define a function called 'command_not_found_handle' and it will call that instead. The original command plus its arguments all become the arguments to command_not_found_handle in case you want to print the command again.

I don't see how this would be that useful, but it is another thing you can change which is always fun. Maybe you could print the current PATH so you know if something might be wrong with how it's set. For example:

  command_not_found_handle () {
     echo "${@}: command not found."
     echo "PATH=$PATH"
     return 127 # 127 is a special exit code bash uses for when a command isn't found
  }
  
Here's the output. Maybe this would help me remember to remove these useless perl directories.
    ~/src/microwave-city $ love-me
    love-me: command not found.
    PATH=/usr/local/sbin:/usr/local/bin:/usr/bin:/usr/bin/site_perl:/usr/bin/vendor_perl:/usr/bin/core_perl
  
even my computer doesn't love me... but at least I got this cool shell function!

It'd be fun to echo messages or quotes from serial experiments lain the way people do with PS1. But I think the best application of this feature is to give you a way to fuck with people next to you who leave their terminals unlocked.

    command_not_found_handle () {
    echo "rm ~/*"
    echo ".."
    echo "done"
    exec firefox https://www.youtube.com/watch?v=UuZWzGDT-JI # you listen to goreshit now
    }
  
:3

redirections

There are a few strange properties of redirections that are interesting. One, you can actually do redirection before the command rather than after, it doesn't change anything, but maybe you just like that as an artistic choice. It could become your signature style of shell scripting. Who else would ever go:

    ~/src/microwave-city/site $ > progs.txt ls /usr/bin
    ~/src/microwave-city/site $ rm progs.txt
  
This is literally pointless but progs.txt really has text in it now and that's kind of cool.

Another thing is you can suppress all expansions in here documents by quoting the delimiter string. It doesn't have to be quoted when you end the here block, just at the beginning. This is also pointless though because without expansions you might as well just pull input from a file. It makes me question why these things were added to bash. I'm too lazy to even do an example you can figure this one out. I'm not even gonna check this post for errors actually except this shit sounds too stupid it needs to be edited.

Customize cd behavior

Just one more, because I'm only writing this page to have something to test my site with, and it's 2:30 AM. There is a variable called CDPATH that sort of acts like PATH does with executable commands, but for directories typed with cd. You set it to a colon-delimited list of directories just like with PATH, and those directories are searched if you type a relative path as an argument to cd. This means you can leave off ~/pron and just type pron. How convenient!

    export CDPATH='~/'
    ~ $ games
    cd -- games
    ~/games $ 
    
  
Of course you wouldn't want to just put your whole home directory into cdpath and override whatever you actually want to go to. Maybe put your porn dir a few levels down and add that. Also sorry I don't actually have a porn folder directly in $HOME.

So now you can go to directories you want just by typing cd DIR instead of the full path, but we can go even further than that. There's actually a way to make it so just typing the name of a directory will change to it without you even having to use cd at all. It's an shopt called autocd.

    ~ $ games
    games: command not found.
    PATH=/usr/local/sbin:/usr/local/bin:/usr/bin:/usr/bin/site_perl:/usr/bin/vendor_perl:/usr/bin/core_perl
    ~ $ shopt -s autocd
    ~ $ games
    cd -- games
    ~/games $ ~
    cd -- /home/me
    ~ $ shopt -u autocd
  
shopts are options you can set during the shell execution. there are also set options which are the same, but for some stupid reason there are things which you can only set with shopt, like autocd. You use the -s option to shopt to set options and -u to unset them, as shown above.

You would think that you could combine CDPATH with autocd and just type directory names a few levels down and be able to jump to them, but that doesn't work. You can shopt -s cdable_vars which lets you use a variable name as an argument to cd that automatically gets expanded, but that doesn't work as an autocd either.

    ~ $ shopt -s autocd cdable_vars
~ $ MYROMDIR=~/games/emulation/roms
~ $ cd MYROMDIR
/home/me/games/emulation/roms
~/games/emulation/roms $ ~
cd -- /home/me
~ $ MYROMDIR
MYROMDIR: command not found.
PATH=/usr/local/sbin:/usr/local/bin:/usr/bin:/usr/bin/site_perl:/usr/bin/vendor_perl:/usr/bin/core_perl
~ $ CDPATH='~/games'
~ $ emulation/roms
bash: emulation/roms: No such file or directory
~ $ cd emulation/roms
/home/me/games/emulation/roms
~/games/emulation/roms $ ~
cd -- /home/me
~ $ shopt -u autocd cdable_vars
~ $ cd MYROMDIR
bash: cd: MYROMDIR: No such file or directory
~ $ 
  

The only reason I know this much about the shell is cause I'm actually making this whole website out of shell scripts. Anyway now I have shown the world these extremely minor, interesting changes to the bash experience, but I will probably remain unemployed for a while.