Useful Bash Command Line Tips and Tricks Examples – Part 4

Continuing our series on useful Bash command line tips and tricks, in today’s article, we will explore grepping only what you need, and start of with a primer on pwd and how to discover the path a script was started from.

In this tutorial you will learn:

  • Useful Bash command line tips, tricks and methods
  • How to interact with the Bash command line in an advanced manner
  • How to sharpen your Bash skills overall and become a more proficient Bash user

Useful Bash Command Line Tips and Tricks Examples - Part 4

Useful Bash Command Line Tips and Tricks Examples – Part 4

Software requirements and conventions used

Software Requirements and Linux Command Line Conventions
Category Requirements, Conventions or Software Version Used
System Linux Distribution-independent
Software Bash command line, Linux based system
Other Any utility which is not included in the Bash shell by default can be installed using sudo apt-get install utility-name (or yum install for RedHat based systems)
Conventions # – requires linux-commands to be executed with root privileges either directly as a root user or by use of sudo command
$ – requires linux-commands to be executed as a regular non-privileged user

Example 1: Path working directory? Or not?

We may be used to calling pwd at the command line to tell us the name of our current directory:

$ pwd
/home/roel/workspace

But if we want to obtain the directory from which a script was started, does using this variable from a script also work the same way?

$ cat test_pwd.sh 
#!/bin/bash
MY_PATH1="${PWD}"
echo "${MY_PATH1}"
MY_PATH2="$(pwd)"
echo "${MY_PATH2}"


We will use two ways to retrieve the path: we look (for the first MY_PATH1 assignment) at the PWD (OS level) automatically-preset variable, and in the second case (for the second MY_PATH2 assignment) we execute pwd in a subshell ($(...)) and assign it to MY_PATH2. Let’s execute the same:

$ ./test_pwd.sh 
/home/roel/workspace
/home/roel/workspace

Looks all good, right? Yes, perhaps, but once we change into a different directory, and call the script by using it’s full or relative path name, the PWD variable (or the pwd command) inside the script will return the directory we were in when the script was started. Let’s verify this:

$ mkdir test
$ cd test
$ ../test_pwd.sh
/home/roel/workspace/test
/home/roel/workspace/test

What we can see here is that pwd (or the $PWD variable) will always return the actual current path.

This may be an issue: we may want to start a subscript, or access a file, from within the same directory (or a subdirectory thereof) as the one where the script was in. This is often the case for more complex Bash scripts which call multiple subscripts and/or data and configuration files.

So what is a uniform way to obtain the path from which the script was started?

One may consider using the dirname "\$0" command:

$ cat test2.sh 
#!/bin/bash
echo "\$0"
dirname "\$0"

Dirname will yield the – relative – directory name of any option passed to it, and in this case that is \$0 – a special variable which is set when a script starts to the name of the script as it was started. Let’s test it:

$ ./test2.sh 
./test2.sh
.
$ cd test
$ ../test2.sh 
../test2.sh
..

Better, I suppose, and it may help a little (to get an idea mainly), but it still does not yield us with a fully qualified pathname. For this, we can use a double subshell wrapper around dirname in combination with an actual full qualified path obtained from a pwd execution:

$ cat make_it_work.sh 
#!/bin/bash
MY_PATH="$(cd "$(dirname "\$0")" && pwd)"
echo "${MY_PATH}"

Let’s see if it works:

$ ./make_it_work.sh 
/home/roel/workspace

So far so good, but does it work when you run it from a subdirectory?

$ cd test && pwd
/home/roel/workspace/test
$ ../make_it_work.sh 
/home/roel/workspace
$ /home/roel/workspace/make_it_work.sh 
/home/roel/workspace

Yes!

We first change into test and verify we are in the test directory, if that change directory (cd) command was successful (as instructed by &&).

In both cases – whether it is called in a relative manner (../), or with a fully qualified path name (/home/roel/workspace/), the result is that we see the directory from which the script was started (/home/roel/workspace/) and not the actual current working directory, or pwd (/home/roel/workspace/test).

In summary, you can use the MY_PATH="$(cd "$(dirname "\$0")" && pwd)" one-liner script to obtain the correct, fully qualified, directory name from within your scripts. After this, using a relative addition will work nicely. For example, you can use ${MY_PATH}/include/mysubscript.sh and even ${MY_PATH}/../one_dir_up_file.txt etc.

Example 2: Grepping only what you need

Have you ever used grep? Grep is a versatile Bash command line utility which lets you select text from a file easily. Most of the time it is used as follows:

$ cat test
line 1 my line
line 2 your lines
line 3 our line
$ grep 'line 2' test
line 2 your lines


We have a input file with 3 lines, and we look for a specific test (line 2) in that file. But how about if you only want the lines which have the multiple of line (i.e. lines) mentioned in them? And, how about if you only wanted to have just the word before it including the lines bit, but not the actual line x output?

In that case, we can grep for only what we need using the -o (‘only’) option to grep:

$ grep -o 'lines' test
lines
$ grep -o '\w\+ lines' test
your lines

Bingo! We first grepped for only the word ‘lines’, which was found. We then prefixed that with a space, and a regular expression which states in pseudo-text: find a word boundary (\w), at least once and as many times as applicable (\+) followed by a space. The result is that your (which has two word boundaries; a start and an end) is included. line 2 is not included. Whilst it has word boundaries, there is no suffix of lines to that one.

If you would like to learn more about regular expressions in Bash, please see Bash Regexps for Beginners with Examples, Advanced Bash Regex with Examples and you may also like the semi-related Python Regular Expressions with Examples.

Conclusion

In this article, we explored pwd and looked at how to use pwd from within a script in combination with dirname to retrieve the fully qualified directory path from which the script was started, in a way which will always work. We also looked at grepping only what we need using the -o option and, in this case, regular expression to match word boundaries.

Leave us a comment with your best Bash command line tips and tricks!



Comments and Discussions
Linux Forum