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,092
  • 41
  • 129
  • 192
TheFisherman
  • 235
  • 1
  • 2
  • 8
  • 9
    set an alias like `alias x='/home/path_to_x/x'`. Don't use `.` before `/home`. `.`(dot) refers to current directory. – sourav c. Oct 15 '14 at 08:05
  • 2
    Does `x` really need to be run while being in `/home/path_to_x`? Or are you just unsure about how to run a program residing in a specific directory? – Adaephon Oct 15 '14 at 08:47
  • possible duplicate of [Execute command with relative (upper) path. Using another working directory](http://askubuntu.com/questions/527156/execute-command-with-relative-upper-path-using-another-working-directory) – c0rp Oct 16 '14 at 06:26
  • One more similar question http://askubuntu.com/questions/427818/how-can-i-run-this-sh-script-without-typing-the-full-path – c0rp Oct 16 '14 at 06:29

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,468
  • 18
  • 29
Useless
  • 300
  • 1
  • 6
  • 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,627
  • 16
  • 118
  • 187
  • 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
  • 116,445
  • 54
  • 318
  • 493
TheFisherman
  • 235
  • 1
  • 2
  • 8
  • 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. `cd`s 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](https://gnu.org/software/bash/manual/bash.html#Command-Execution-Environment). 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](http://askubuntu.com/a/537308), 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,092
  • 41
  • 129
  • 192
  • 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