9

I wish to create an alias, which runs program x, without changing the current directory I am in. What I have now is:

alias x = "cd /home/path_to_x && ./x"

This works, but changes my directory. What I wish to do is something like:

alias x="./home/path_to_x/x

But then I get no such file or directory. Anyone know a workaround for this?

4

5 Answers 5

14

DON'T CD, just run it using its absolute path

This version:

cd /home/path_to_x && ./x

changes directory to an absolute path (you see how /home/... starts at the root directory) and then runs the executable at the relative path ./x (that is, relative to the new working directory).

This version:

./home/path_to_x/x

tries to run the executable at the relative path ./home/path_to_x/x, which means relative to whatever your current working directory is now. That explains why you get the error - this relative path really doesn't exist.

The command you want would be:

/home/path_to_x/x

using the absolute path (starting at the root directory /) again.

Oh, and you can also just add /home/path_to_x to your PATH instead of creating the alias. See: How to run scripts without typing the full path?

4
  • This is the correct answer for the question as posed. Oct 15, 2014 at 21:34
  • 1
    This would only be incorrect if the program needed to be run in a specific directory that it gets from pwd
    – Kaz Wolfe
    Oct 15, 2014 at 23:06
  • @Whaaaaaat is right. /home/path_to_x/x is not functionally equivalent to (cd /home/path_to_x && ./x); if it works or not is application dependent.
    – Rmano
    Oct 16, 2014 at 9:13
  • Although you're right in general, for this specific question OP was visibly trying to run from the absolute path (just with a one-character mistake). However, I'm sure they can clarify if working directory is important in this case.
    – Useless
    Oct 16, 2014 at 10:24
8

If you do not want the cd to stick after the alias substitution, use a subshell with ( y ):

alias my_x="(cd /home/path_to_x && ./x)&" 

you can check it with

alias test_y="(cd /tmp && sleep 10 ) & "

Note that the solution

alias my_y="/home/path_to_x/x" 

is not exactly equivalent. In fact, if called via my_x, the x program is run with a current directory /home/path_to_x/, while if called by my_y, x is run with a current directory which is the one where the command my_y was issued. This can be important or not depending on what x is doing.

About the OP solution, it works in bash:

romano@RRyS:~$ pwd
/home/romano
romano@RRyS:~$ alias x="cd /bin && ./echo A >/dev/null  &"
romano@RRyS:~$ x
[1] 16611
romano@RRyS:~$ pwd
/home/romano

but not in zsh:

[romano:~] % pwd
/home/romano
[romano:~] % alias x="cd /bin && ./echo A >/dev/null &"
[romano:~] % x
[1] 16744
[1]  + 16744 done       ./echo A > /dev/null                                    
1& [romano:/bin] % pwd
/bin
[romano:/bin] % 

It seems that bash and zsh execute lists in different ways ...so it's better to add the explicit parenthesis... thanks @EliahKagan for pointing it to me.

1
  • 1
    Giving the trailing & higher precedence than && seems like it may be unique to zsh. I tried sleep 5 && echo done & in zsh, bash, ksh, mksh, dash, and even one non-Bourne-style shell (tcsh). Only zsh evaluated sleep 5 in the foreground; all the others returned immediately (then also printed done five seconds later, of course). On the other hand, even if this is entirely a peculiarity of zsh, I think adding explicit ( ) (or { ;}) is reasonable, as it conveys the intent to other humans (or to oneself, when reading the script or history later). Oct 15, 2014 at 19:37
4

If the file which you want to run is already executeable, why don't you add it to you PATH variable?

If your executable file is /home/user/aplication/appX just enter

PATH=$PATH:/home/user/application

to your ~/.bashrc or ~/.profile

After restarting your console, you can run it simply with appX

I think this is the most clean solution.

3

Putting a & at the end seems to do the trick:

alias x = "cd /home/path_to_x && ./x &"
6
  • 2
    Are you sure? After executing x you are in /home/path_to_x. The & at the end simply send the process in background.
    – Rmano
    Oct 15, 2014 at 8:33
  • 2
    @Rmano This actually works. cds in background jobs don't affect the caller (which makes sense--it'd be really weird if they did). This is because asynchronous execution uses a subshell. Though this would be better if it explained why it works and what & does--and how running in the background is sometimes undesirable--this is (already) a correct answer. (Explicitly making a subshell with ( ) syntax, as you suggest, is probably a better solution most of the time though.) Oct 15, 2014 at 13:46
  • @EliahKagan you are right. I checked the solution with zsh and effectively it works in bash and not in zsh... must be some difference in how the aliases are expanded.
    – Rmano
    Oct 15, 2014 at 15:24
  • Asked a question: unix.stackexchange.com/questions/162286/…
    – Rmano
    Oct 15, 2014 at 15:42
  • @Rmano did you enable the settings related to pushd in zsh (I have setopt autopushd pushdsilent pushdtohome, and it remembers my cwd.)
    – muru
    Oct 15, 2014 at 16:07
0

Get Backup of your current pwd and and after running your command, undo your last pwd.

alias x='dwp=$(pwd) && cd /home/path_to_x && ./x && cd $dwp'
3
  • You misunderstood the effect of that Rmano's alias. The command line is not blocked. It's just that the output of the alias (test) pushed the cursor to the next line. You can still do whatever you want there (including pressing enter to open a fresh new prompt).
    – muru
    Oct 15, 2014 at 16:05
  • yup, yes correct. @mure :| Oct 15, 2014 at 16:07
  • Note that since you use double quotes the variable will include the current directory at the time the alias is defined. Use single quotes to defer evaluation until the alias is expanded. However, pushd and popd do what your answer does. alias x='pushd /home/path_to_x && ./x && popd' Oct 15, 2014 at 21:39

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .