How do I run a program with a different working directory from current, from Linux shell?
Using a Linux shell, how do I start a program with a different working directory from the current working directory? For example, I have a binary file helloworld that creates the file hello-world.txt in the current directory.
This file is inside of directory /a . Currently, I am in the directory /b . I want to start my program running ../a/helloworld and get the hello-world.txt somewhere in a third directory /c .
I discovered the hard way that su resets the working directory to the home directory of user you specify before running any -c commands. This was very helpful to me.
It’s been 12 years since I’ve posted this question and today I looked it up myself, cause I could not recall how to do that.
It’s one thing to come back to a SO post with a:visited link and an upvote already on it. It’s another thing when you’re the asker, or even the answerer. There should be a badge for that. «Forgetful»
11 Answers 11
Call the program like this:
The parentheses cause a sub-shell to be spawned. This sub-shell then changes its working directory to /c , then executes helloworld from /a . After the program exits, the sub-shell terminates, returning you to your prompt of the parent shell, in the directory you started from.
Error handling: To avoid running the program without having changed the directory, e.g. when having misspelled /c , make the execution of helloworld conditional:
Reducing memory usage: To avoid having the subshell waste memory while hello world executes, call helloworld via exec:
[Thanks to Josh and Juliano for giving tips on improving this answer!]
the entire () construct will have the exitcode of the last command inside. You can check that either directly through chaining or by inspecting $? .
Similar to David Schmitt’s answer, plus Josh’s suggestion, but doesn’t leave a shell process running:
This way is more similar to how you usually run commands on the shell. To see the practical difference, you have to run ps ef from another shell with each solution.
Just say it here — exec replaces the shell process with the given command, without creating a new process.
An option which doesn’t require a subshell and is built in to bash
$ pwd /home/abhijit $ pushd /tmp # directory changed $ pwd /tmp $ popd $ pwd /home/abhijit
A similar suggestion has been done below by Sahil. It does not work if the command fails. Consider pushd SOME_PATH && run_stuff && popd — if run_stuff fails, than popd is not going to be executed.
Late reply, that depends on the settings of the bash file. Bash can continue executing commands even after a failed command (unlike using &&), but it can be set to not do that using set -e in the file and then it would fail to popd .
Still, I think pushd «$
I think you’d need to write a shell script to which you would pass the parameter that would execute the series of commands as you can’t pass a parameter in the middle of an alias. If you need help writing that, you should ask a separate question and reference this one. Once you have the shell script, you could write an alias to call your new script.
Just change the last «&&» into «;» and it will cd back no matter if the command fails or succeeds:
I always think UNIX tools should be written as filters, read input from stdin and write output to stdout. If possible you could change your helloworld binary to write the contents of the text file to stdout rather than a specific file. That way you can use the shell to write your file anywhere.
$ cd ~/b $ ~/a/helloworld > ~/c/helloworld.txt
cd SOME_PATH && run_some_command && cd —
the last ‘cd’ command will take you back to the last pwd directory. This should work on all *nix systems.
One way to do that is to create a wrapper shell script.
The shell script would change the current directory to /c, then run /a/helloworld. Once the shell script exits, the current directory reverts back to /b.
Here’s a bash shell script example:
If you always want it to go to /C, use an absolute path when you write the file.
The following worked for my simple need to set up an alias to which I can append an argument, without having to put the instructions in a function; worked in Bash and ZSH:
$ CWD=/your/target/dir command args
My use case: I have a shell script named run-service that resolves paths to other files based on its own location. If I call it with cd ~/Code/company/scripts && run-service dev/some-service , it will expect to find a config file in ~/Code/company/services/dev/some-service . So instead of always having to cd into the directory and calling the script, I just did this:
# Alias definition alias run-service="CWD=/your/target/dir run-service" # Calling the alias $ run-service foo
It’s probably too simplistic to be of general use, but it works for my basic use-case.
cwd(3) — Linux man page
This module provides functions for determining the pathname of the current working directory. It is recommended that getcwd (or another *cwd() function) be used in all code to ensure portability.
By default, it exports the functions cwd(), getcwd(), fastcwd(), and fastgetcwd() (and, on Win32, getdcwd()) into the caller’s namespace.
getcwd and friends Each of these functions are called without arguments and return the absolute path of the current working directory. getcwd
Exposes the POSIX function getcwd(3) or re-implements it if it’s not available. cwd
The cwd() is the most natural form for the current architecture. For most systems it is identical to ‘pwd’ (but without the trailing line terminator). fastcwd
It might conceivably chdir() you out of a directory that it can’t chdir() you back into. If fastcwd encounters a problem it will return undef but will probably leave you in a different directory. For a measure of extra security, if everything appears to have worked, the fastcwd() function will check that it leaves you in the same directory that it started in. If it has changed it will "die" with the message «Unstable directory path, current directory changed unexpectedly». That should never happen. fastgetcwd
my $cwd = getdcwd(); my $cwd = getdcwd('C:');
The getdcwd() function is also provided on Win32 to get the current working directory on the specified drive, since Windows maintains a separate current working directory for each drive. If no drive is specified then the current drive is assumed.
This function simply calls the Microsoft C library _getdcwd() function.
abs_path and friends These functions are exported only on request. They each take a single argument and return the absolute pathname for it. If no argument is given they’ll use the current working directory. abs_path
my $abs_path = abs_path($file);
Uses the same algorithm as getcwd(). Symbolic links and relative-path components («.» and «..») are resolved to return the canonical pathname, just like realpath(3). realpath
my $abs_path = realpath($file);
my $abs_path = fast_abs_path($file);
$ENV< PWD > If you ask to override your chdir() built-in function,
then your PWD environment variable will be kept up to date. Note that it will only be kept up to date if all packages which use chdir import it from Cwd.
Notes
• Since the path seperators are different on some operating systems (‘/’ on Unix, ‘:’ on MacPerl, etc. ) we recommend you use the File::Spec modules wherever portability is a concern.
• Actually, on Mac OS , the "getcwd()", "fastgetcwd()" and "fastcwd()" functions are all aliases for the "cwd()" function, which, on Mac OS , calls ‘pwd’. Likewise, the "abs_path()" function is an alias for "fast_abs_path()".
Author
Originally by the perl5-porters.
Maintained by Ken Williams
Copyright
Copyright © 2004 by the Perl 5 Porters. All rights reserved.
This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself.
Portions of the C code in this library are copyright (c) 1994 by the Regents of the University of California. All rights reserved. The license on this code is compatible with the licensing of the rest of the distribution — please see the source code in Cwd.xs for the details.
How can I get the current working directory? [duplicate]
I want to have a script that takes the current working directory to a variable. The section that needs the directory is like this dir = pwd . It just prints pwd how do I get the current working directory into a variable?
This is not a duplicate of the question for which it is currently marked as one. The two questions should be compared, at least, based on their titles (as well as their answers). That the answer to this question is already covered by another is, or should be, irrelevant.
@KennyEvitt actually, one of the main reasons we close is precisely because an answer has been given elsewhere. And, in fact, the main question here is actually how to assign the output of a command to a variable, which is covered by the dupe. I have also given the answer to this specific case, so all bases are covered. There would be no benefit in opening this again.
@terdon As a resource available, and intended, for the entire population of Unix & Linux users, this is a valuable question, even if the original asker really just needed an answer already covered elsewhere. If anything, I think this question should be edited to more closely match its title and it should be re-opened, not to allow further activity, but to not imply that this question is ‘bad’.
@KennyEvitt closing as a duplicate in no way implies that the question is bad! This question will remain here, answered, for ever. If you really want to know how to get the current working directory, you will find your answer here. If you just want to know how to save the output of a command in a variable, you will also find the answer here by following the link to the dupe. In any case, this isn’t really something I should do alone, if you feel strongly that it should be reopened, please open a discussion on Unix & Linux Meta where such things should be resolved.
5 Answers 5
There’s no need to do that, it’s already in a variable:
The PWD variable is defined by POSIX and will work on all POSIX-compliant shells:
Set by the shell and by the cd utility. In the shell the value shall be initialized from the environment as follows. If a value for PWD is passed to the shell in the environment when it is executed, the value is an absolute pathname of the current working directory that is no longer than bytes including the terminating null byte, and the value does not contain any components that are dot or dot-dot, then the shell shall set PWD to the value from the environment. Otherwise, if a value for PWD is passed to the shell in the environment when it is executed, the value is an absolute pathname of the current working directory, and the value does not contain any components that are dot or dot-dot, then it is unspecified whether the shell sets PWD to the value from the environment or sets PWD to the pathname that would be output by pwd -P. Otherwise, the sh utility sets PWD to the pathname that would be output by pwd -P. In cases where PWD is set to the value from the environment, the value can contain components that refer to files of type symbolic link. In cases where PWD is set to the pathname that would be output by pwd -P, if there is insufficient permission on the current working directory, or on any parent of that directory, to determine what that pathname would be, the value of PWD is unspecified. Assignments to this variable may be ignored. If an application sets or unsets the value of PWD, the behaviors of the cd and pwd utilities are unspecified.
For the more general answer, the way to save the output of a command in a variable is to enclose the command in $() or ` ` (backticks):
Of the two, the $() is preferred since it is easier to build complex commands like:
command0 "$(command1 "$(command2 "$(command3)")")"
Whose backtick equivalent would look like:
command0 "`command1 \"\`command2 \\\"\\\`command3\\\`\\\"\`\"`"