1

I have a little script I wrote that lets me change to the directory of a script that's on the path, which helps me quickly get to other scripts I tend to want to edit, in the same folder as the original script.

I tend to do this by going one back in history, and prefixing that command, no matter what it was, like so

$ . cdbin my_super_script

This works most of the time - but - it doesn't work when the last command I was running was being piped somewhere,

e.g.

# if my last command was the following
$ my_super_script | grep -v bad | grep good

then when I try and run my cdbin script using history, it looks like this

$ . cdbin my_super_script | grep -v bad | grep good

and then that just doesn't do anything - no errors, it just leaves me in my current directory.

Here's my simple cdbin script:

cdbin

PROG=$(which "$1")
DIR=$(dirname "$PROG")
cd "$DIR" 

EDIT: Note I am aware that I could simply type something like the following most of the time to avoid this, e.g. $ . cdbin !:0 but find that a touch awkward to type :D

Brad Parks
  • 1,669

1 Answers1

2

When you run this with a pipeline, your . cdbin command runs in a subshell: so it changes directories in the subshell, and the effect is lost when the subshell closes.

To avoid this, since you’re only interested in the command you ran previously, use the history:

. cdbin !!:0

This will extract the first word of the previous command, so in your scenario you’d end up with

. cdbin my_super_script

You can use fc instead to extract the previous command:

. cdbin $(fc -l -1 | awk '{print $2}')

That can be turned into an alias to make it simpler to use, or made part of cdbin itself, for example if it’s invoked without any arguments:

CMD=${1:-$(fc -l -1 | awk '{print $2}')}
PROG=$(which "$CMD")
DIR=$(dirname "$PROG")

cd "$DIR"

unset CMD PROG DIR

Stephen Kitt
  • 434,908