7

I have a simple script that I want to invoke 'pushed' followed by another command. But the 'pushd' command inside the script doesn't seem to stick past the script.

What's a way to make this execute in the shell terminal?

#!/bin/sh

pushd $1
time

What I really want to accomplish is invoke pushd followed by other-command with one command.

1

3 Answers 3

8

A shell script normally executes in a separate instance of the shell program, /bin/sh in this case. Your pushd command affects that sub-shell's working directory only. If it were otherwise, any program you ran from the shell could mess with your shell's working directory.

To execute that script within the current shell, say this instead:

$ . my-command somedir

or, more verbosely:

$ source my-command somedir

To make it appear that your program works like any other, you can use an alias:

$ alias mycmd='source my-command'
$ mycmd /bin
$ pwd
/bin
7
  • What I really want is execute 'pushd <params>' followed by another command that takes no params. I may not need a shell script for it - what's a good way to do this?
    – Sarah Soto
    Dec 29, 2010 at 0:23
  • @sarah-soto All you need then is pushd <params>; other-command Dec 29, 2010 at 0:26
  • I should have clarified: I want a shortcut so I am invoking both commands one after the after without implicitly calling both. I can't aliase the two commands to be alias p2='pushd; other-command' and then invoke 'p2 ~/temp' as the shell will return the error: '-bash: pushd: no other directory
    – Sarah Soto
    Dec 29, 2010 at 0:38
  • You could use a shell function: function p2 () { pushd "$@"; other-command;}
    – Steven D
    Dec 29, 2010 at 0:46
  • 2
    A shell script is a fine way to do this. It's inefficient, but this is not a case where optimization is worth bothering with. Defining a shell function in your ~/.bash_profile (or whatever your shell uses, if not Bash) will also work. Your choice. Dec 29, 2010 at 3:10
2

Scripts cannot alter their parent processe's environment. Because of this, any environment changes made in the script are lost.

To run the script in the same process, you can 'source' the script like this

. /path/to/script.sh args
0

Instead of a shell script, function is more appropriate for this kind of operation, especially when using pushd.

Add this in .bashrc:

foo() {
    pushd $1
    time
}
export foo

In shell:

$ foo mydir1

output:

~/mydir1 ~

real    0m0.000s
user    0m0.000s
sys     0m0.000s

You must log in to answer this question.