DEV Community

Cover image for Bash Script Tool Kit

Bash Script Tool Kit

Jimmy McBride on December 16, 2019

In my blog Write A Bash Script 101, I write about how to make a simple bash script from scratch. The purpose of this blog is to serve as a referenc...
Collapse
 
moopet profile image
Ben Sinclair

I've never been a fan of pushd for directory stacks, mostly because I get confused with more than one place to return to (which I'll use cd - for) so the benefit is probably lost on me. But one place I wouldn't use them is inside a script, because unless you're careful and trap things to clean up nicely, it'll mess you up if your script exits early.

Collapse
 
jimmymcbride profile image
Jimmy McBride

I've been using them in mine and haven't had any issues so far. What kind of problems can using pushd in a script cause? Also, how do you trap things to clean up when using pushd in your scripts?

Collapse
 
moopet profile image
Ben Sinclair

What it is, is that if I'm in a "non-trivial" script, and I'm using pushd and popd to keep a stack of where I am, and one function fails - for example, if pushd doesn't succeed because the directory is missing - then all subsequent commands will think I'm in the wrong place and potentially do destructive things.

On the face of it, cd has the same pitfalls, and if everything was defensively programmed, it wouldn't matter:

if ! cd "$path"; then
  # do some recovery
fi

if ! push "$path"; then
  # do some recovery
fi

But if that's what we're doing, we might as well use absolute paths and program defensively everywhere.

By trapping I mean things like this:

trap clean_up EXIT

clean_up() {
  # do whatever we need to put the system back where we left it.
}

Given that scripts can be sourced as well as executed, changing directory within a script might or might not change the directory of the calling shell.

Thread Thread
 
jimmymcbride profile image
Jimmy McBride

Sick! That's some pretty cool stuff. I'm going to look into that some more. Thank you for sharing!

Collapse
 
vlasales profile image
Vlastimil Pospichal
$ NAME="Jimmy     McBride"
$ echo $NAME
Jimmy McBride
$ echo "$NAME"
Jimmy     McBride

Use quotes!

Collapse
 
jimmymcbride profile image
Jimmy McBride

Fair enough. I see your point.

Collapse
 
jdeisenberg profile image
J David Eisenberg • Edited

I have tried pushd .. to move up one directory level without breaking the pushd/popd chain, and it seems to work great. I’m using GNU bash, version 5.0.7(1)-release

Collapse
 
jimmymcbride profile image
Jimmy McBride

That's really great news! I'm going to give it a shot!

Collapse
 
bsutton profile image
Brett Sutton

It might be worth mentioning that whilst push and pop sound lovely they are a really bad idea to use. You should always use relative or absolute paths and not change directories.

Collapse
 
jimmymcbride profile image
Jimmy McBride

Well you change directories with cd, that's what cd means, change directory. I haven't run into any problems with pushd/popd at all in my experience. I use them in my alias's and my bash scripts and they've done perfectly fine so far. When you use pushd you are always using a relative or an absolute path.

Collapse
 
rpalo profile image
Ryan Palo

What’s the reasoning behind that? What pitfalls does this help avoid?

Collapse
 
bsutton profile image
Brett Sutton

So there are several problems:

What happens if you call a function that changes the working directory to something like '/'.

Your code thinks that you are in /home/me/tempstuff

You then run 'rm -rf .'

You just deleted your entire file system.

What happens if another process deletes your working directory?
What directory are you in now?

By always using relative or absolute paths you know you are operating on the correct directory.

Yes, lots of people use cd/pushd/popd and yes, they work as expected.

The problem is that they are risky and best practice says to stay away from them.

Personally I dislike Bash to the extent that I've written a tool to replace it. If you are interested in using a modern programming language to write scripts have a look at:

pub.dev/packages/dshell

Collapse
 
ilancb4 profile image
ilancb4

Thanks for the post :)

Minor copy&paste in the section explaining the use of copy the first example uses the command 'mv' instead of 'cp'.

Collapse
 
jimmymcbride profile image
Jimmy McBride

Ha! Thanks for pointing it out! Fixed!