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?

αғsнιη
  • 35,660

5 Answers5

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?

Olorin
  • 3,488
Useless
  • 300
  • This is the correct answer for the question as posed. – Dennis Williamson Oct 15 '14 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 '14 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 '14 at 09: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 '14 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.

Rmano
  • 31,947
  • 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). – Eliah Kagan Oct 15 '14 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.

0xAffe
  • 297
  • 1
  • 9
3

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

alias x = "cd /home/path_to_x && ./x &"
Eliah Kagan
  • 117,780
  • 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 '14 at 08: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.) – Eliah Kagan Oct 15 '14 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 '14 at 15:24
  • Asked a question: http://unix.stackexchange.com/questions/162286/difference-of-behavior-in-bash-and-zsh – Rmano Oct 15 '14 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 '14 at 16:07
  • @muru getopt autopushd pushdsilent pushdtohome says -- pushdsilent pushdtohome (I think it's the default) – Rmano Oct 15 '14 at 16:17
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'
αғsнιη
  • 35,660
  • 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 '14 at 16:05
  • yup, yes correct. @mure :| – αғsнιη Oct 15 '14 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' – Dennis Williamson Oct 15 '14 at 21:39