So at my position we use a shared set of aliases to do builds. Something like...

alias 'build'='cd $BUILD_ROOT; m; cp ...; cp...; deploy; deploy; deploy; cd -'

This is super irritating because the make command takes about 3 minutes and I usually realize I missed something, hit Ctrl-C, and then immediately run build again. This leaves me in a directory I don't care to be in, with a painful path to retype.

What I'd really like is something like...

alias 'betterbuild'='pushd .; build; even-if-the-user-cancelled popd'

Is there a way to do this?

  • I'ma head off the obvious answers to this: use a script. I really want to keep using the same command as the rest of the team so as they modify their scripts I keep up. Other aliases and scripts depend on this alias and I want those to continue to work.
    – Hounshell
    Aug 2, 2013 at 16:26
  • 6
    This is exactly the sort of things scripts are meant for.
    – user
    Aug 2, 2013 at 16:27
  • Is the cp ... supposed to be cd ....?
    – terdon
    Aug 2, 2013 at 17:59
  • @terdon: I think the dots represent missing text.
    – user26112
    Aug 2, 2013 at 18:21

2 Answers 2


Well, I was going to say make it a script, because aliases aren't really meant to do complex things like this and scripts are meant for more-complex or longer-running tasks. Aliases are basically meant to map one command to another, for example to provide default parameters to a command that doesn't support that natively.

However, since you stated in a comment that you want to keep this an alias, we'll have to figure out how to do what you want within the boundaries of an alias.

The natural choice then becomes to launch a subshell from within the alias. For example:

~$ alias xyz1='( cd ~/tmp; sleep 10; cd ~ )'
~$ alias xyz2='cd ~/tmp; sleep 10; cd ~'
~$ xyz2
~/tmp$ cd
~$ xyz1

This changes the working directory only within the subshell, which exits when either the alias finishes executing normally, or is aborted e.g. through Ctrl+C.

  • Looks like you and Evan are having a "!$" moment 8-).
    – slm
    Aug 2, 2013 at 16:57
  • @slm Yes, we did end up saying pretty much the same thing at pretty much the same time. I'll let the community decide who did better :)
    – user
    Aug 2, 2013 at 16:59
  • I did my part and +1'd you both 8-).
    – slm
    Aug 2, 2013 at 17:00

You may be able to use a subshell.

alias build='( cd $BUILD_ROOT; m; cp ...; cp...; deploy; deploy; deploy; )'

In the above example, cd $BUILD_ROOT changes the current working directory of the subshell, but not the interactive shell that calls the alias. For a generic case, you can use a subshell and an exit trap.

alias build='( cleanup() { do; cleanup; }; trap cleanup EXIT; cd $BUILD_ROOT; m; cp ...; cp...; deploy; deploy; deploy; )'

Do reconsider using a script though. The above example would look much cleaner in a script. Scripts are interpreted in their own shell instances. The subshell syntax would not be necessary in a script.

You mentioned in a comment that scripts depend on your alias. This suggests that you are sourcing your scripts instead of executing them, which is generally a bad practice. Also, you mentioned that there are aliases that depend on your alias. You can use scripts within aliases.

  • More generally, processes are executed in a context separate from the invoking shell. A shell script just happens to be a slightly special kind of process invocation.
    – user
    Aug 2, 2013 at 16:34
  • @MichaelKjörling: Thanks. I modified that part of my answer.
    – user26112
    Aug 2, 2013 at 16:53

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.