Fun with BASH
Part 1: Scripting
Ever find yourself typing out the same long command line groups over and over?
BASH scripting can help!
Let's say you want to want to commit and push to your git repo in one command instead of doing it separately.
(Note on code examples: >$ will be used to indicate the terminal and --> the output from entering that command)
Let's get started:
Open your terminal - we're going to be working your root directory. Create a new file. the .sh extension is usually used on BASH scripts
>$ touch commitpush.sh
Before we edit the script we're going to need to make this file executable. Because right now if we try to execute it we get an error.
>$ ./commitpush.sh --> bash: ./commitpush.sh: Permission denied
To do this we use the chmod command which stands for change-mode. We're going to call it on our script with the flag a+x. This will make this file executable for all users. see the man page for chomod for other options. If you want to remove executability use the flag a-x
>$ chmod a+x commitpush.sh
One last thing before we can start on the script, we need to find out where BASH is on your computer so we can tell the script where to look to execute itself.
>$ whereis bash --> /bin/bash
Note my OSX system has bash in the root bin/ folder but yours might be different.
Time to start editing the script file!
First is to use that info we got from whereis to tell the script where to look to execute itself. This is done with the #! character. Adding the following to your file
#!{yourBASHPATH}
echo This is Working!!!
Now you can execute this script
>$ ./commitpush.sh ---> This is Working!!!
Nice but doesn't help us with much, let's change it to actually have some functionality.
#!/bin/bash
git commit -a
git push
Note using the -a flag on git commit will only commit changes to files that have already being tracked by git, you'll still need to git add any new files.
Well now have a script to save us typing two lines every time, but it's not easy to call it. You're probably used to running bash commands by just typing their name, but if you've noticed every time we've run this script we've prefaced it with ./
This is because as a security measure BASH won't let you execute just any file by name, even if you're in the directory.
>$ commitpush.sh --> -bash: commitpush.sh: command not found
There's another inconvenience issue as well - while a bash script executes in whatever the current directory is, you will still have to reference its current location to execute it. If you're several layers deep this can be irritating.
Let's say your git project is located in ~/codesmith/gitRepos/myProject/ in order to run the script in your home directory you'd have to enter:
../../../commitpush.sh
Luckily there's a built-in system we can use, the $PATH environment variable. You can see your using the echo command:
>$ echo $PATH --> /usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin
Each of these directories is where BASH will look in order to execute a command. So one thing we can do is put our script in one of these directories. I recommend the /usr/local/bin since its less likely to interfer with any built in system commands.
We can move it in using the move (mv) command.
>$ cd
-Gets us back to the home directory
>$ sudo mv commitpush.sh /usr/local/bin
- moves script to the local bin.
The directory we're putting it in is protected so you'll need to use sudo
and enter your password to get it.
Now you can just type commitpush.sh from any directory where you have an active git repo and it will take care of the rest!
One thing to note is using this method means your commit message will open in vi. Get into 'INSERT' mode by hitting the i key then type your message. Exit and save in vi by hitting '[Esc] : w q [enter]'
If you don't like this, then read on and I'll cover how to do this without messing with vi.
Pt 2 - Checking for errors and varibles
So this works in the ideal case, but what if there are errors with your commit? We don't want to push when there is something wrong so this should have some logic keep that from happening. We can do this in our script with exit codes and some conditionals.
Exit codes
Every command that runs in BASH is supposed to return an exit code. This is 0 if everything went as expected and not 0 in the case of anything else. Usually, it's 1 but non-zero is the important part.
This is stored in the BASH varible $? and you can see it by using the echo command.
Success example
>$ cp cp.sh commitpushCOPY.sh
>$ echo $? ----> 0
Failure example
>$ cp MADEUPFILE.sh commitpushCOPY.sh ---> No such file or directory
>$ echo $? ----> 1
Something that can be tricky here is that 'echo $?' its self is a command so it will set the exit code when it runs
>$ cp MADEUPFILE.sh commitpushCOPY.sh ---> No such file or directory
>$ echo $? ----> 1
>$ echo $? ----> 0
Now to put it in our script.
#!/bin/bash
git commit -a
if [ $? = 0 ]
then
git push
fi
Note the how instead of curley braces this uses fi to end the block. Let's add some output to make this more user friendly and to show how the if then/else works in scripting. The comparison is done with a single = operator not the usual === you've been used to in JS.
#!/bin/bash
git commit -a
if [ $? = 0 ]
then
echo 'Commit success, pushing'
git push
else
echo 'Commit failure, aborting push'
fi
Now at least it will be a little more robust and not push anything when we don't expect it to.
But there's still one annoying thing this script does and that's forcing us to enter our commit message in vi and then try to remember how to write-quit vi.
The final entry here will be how to avoid that using parameters.
You're already used to using these. Anything that comes after the command you're using is a parameter. This is commonly flags -a --save or file names that the program needs to use.
using them in a bash script is pretty straight forward. Each space separated value will come in as a bash variable with a number following it.
Script foo.sh
#!/bin.bash
echo $1
echo 'Line of text'
echo $2
echo 'More text'
echo $3
echo 'and even more text'
Running the above script we get
>$ ./foo.sh bar baz
bar
Line of text
baz
More text
and even more text
See how bar and baz are listed and there's an empty line since there is no $3 argument provided.
So using this and the -m flag with git commit we can avoid vi.
#!/bin/bash
git commit -a -m $1
if [ $? = 0 ]
then
echo 'Commit success, pushing'
git push
else
echo 'Commit failure, aborting push'
fi
Now you can commit and push your change with one line!
`>$ commitpush.sh 'Commit and push progress on the current branch'
You'll have to put quotes around your message otherwise your commit message will just be one word.
If you want to avoid this - add in error checking that will abort the entire script if more than one parameter is provided.
Happy coding!!!
Pt 2: Aliases
https://dev.to/sirclesam/fun-with-bash-pt-2-aliases-2imj
Top comments (0)