How to Run a Program With a Different Working Directory from Current, from Linux Shell

How do I run a program with a different working directory from current, from Linux shell?

Call the program like this:

(cd /c; /a/helloworld)

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:

(cd /c && /a/helloworld)

Reducing memory usage: To avoid having the subshell waste memory while hello world executes, call helloworld via exec:

(cd /c && exec /a/helloworld)

[Thanks to Josh and Juliano for giving tips on improving this answer!]

Temporarily change current working directory in bash to run a command

You can run the cd and the executable in a subshell by enclosing the command line in a pair of parentheses:

(cd SOME_PATH && exec_some_command)

Demo:

$ pwd
/home/abhijit
$ (cd /tmp && pwd) # directory changed in the subshell
/tmp
$ pwd # parent shell's pwd is still the same
/home/abhijit

How can I run my script from anywhere(outside the current directory) in my system?

In Unix systems, absolute paths start with / . So you can use absolute path to run a script. In your case all you have to do is run this command from the terminal
sh /home/testing/program/test.sh . It does not matter from which directory you run the command from until you use the absolute path of the script.

Also the file in which the output is written should be defined with absolute path in script file. For example, in your case

/home/centos/rr/email-body.txt

so that the file is recognized by the OS even when the script is executed from the other directory or from any directory whatsoever.

How to run a Linux shell command from a different directory without getting there?

You can try:

me@mypc:~$ (cd ~/my/source/code/directory; make)

Parentheses tell your shell to spawn a separate subshell, with its own current directory, and run the commands inside that subshell. After the command finishes, the subshell is closed, and you're back to your main shell, whose current directory never changed.

execute a subcommand in a different directory as the current one in fish?

Right, many of us coming from Posix shells like bash or zsh are used to being able to run a command substitution like this using $() or just backticks and leave the parent shell environment untouched. It's a nice trick, IMHO.

On the other hand, fish doesn't automatically create a subshell when using its command substitution operator (). There's a feature request here for that, but the workaround (as suggested there) is fairly straightforward -- Just explicitly create a subshell inside the command substitution. E.g.:

mv (fish -c 'cd ~/Downloads; ls -t | head -1 | xargs -I {} readlink -f {}') ./

The downside is that syntax highlighting/checking doesn't work in the quoted text, and quoting/escaping rules get more complicated.

How can Bash execute a command in a different directory context?

You can use the cd builtin, or the pushd and popd builtins for this purpose. For example:

# do something with /etc as the working directory
cd /etc
:

# do something with /tmp as the working directory
cd /tmp
:

You use the builtins just like any other command, and can change directory context as many times as you like in a script.

Using bash to loop through nested folders to run script in current working directory

Another, perhaps more flexible, approach to the problem is to use the find command with the -exec option to run a short "helper-script" for each file found below a directory path that ends in ".7". The -name option allows find to locate all files ending in ".7" below a given directory using simple file-globbing (wildcards). The helper-script then performs the same operation on each file found by find and handles moving the result.h5 to the proper directory.

The form of the command will be:

find /path/to/search -type f -name "*.7" -exec /path/to/helper-script '{}` \;

Where the -f option tells find to only return files (not directories) ending in ".7". Your helper-script needs to be executable (e.g. chmod +x helper-script) and unless it is in your PATH, you must provide the full path to the script in the find command. The '{}' will be replaced by the filename (including relative path) and passed as an argument to your helper-script. The \; simply terminates the command executed by -exec.

(note there is another form for -exec called -execdir and another terminator '+' that can be used to process the command on all files in a given directory -- that is a bit safer, but has additional PATH requirements for the command being run. Since you have only one ".7" file per-directory -- there isn't much benefit here)

The helper-script just does what you need to do in each directory. Based on your description it could be something like the following:

#!/bin/bash

dir="${1%/*}" ## trim file.7 from end of path
cd "$dir" || { ## change to directory or handle error
printf "unable to change to directory %s\n" "$dir" >&2
exit 1
}

destdir="/Result_Folder/$dir" ## set destination dir for result.h5
mkdir -p "$destdir" || { ## create with all parent dirs or exit
printf "unable to create directory %s\n" "$dir" >&2
exit 1
}

ls *.pc 2>/dev/null || exit 1 ## check .pc file exists or exit

file7="${1##*/}" ## trim path from file.7 name

pc_script -f "$file7" -flags1 -other_flags ## first run

## check result.h5 exists and non-empty and copy to destdir
[ -s "result.h5" ] && cp -a "result.h5" "$destdir/new_result1.h5"

pc_script -f "$file7" -flags2 -other_flags ## second run

## check result.h5 exists and non-empty and copy to destdir
[ -s "result.h5" ] && cp -a "result.h5" "$destdir/new_result2.h5"

Which essentially stores the path part of the file.7 argument in dir and changes to that directory. If unable to change to the directory (due to read-permissions, etc..) the error is handled and the script exits. Next the full directory structure is created below your Result_Folder with mkdir -p with the same error handling if the directory cannot be created.

ls is used as a simple check to verify that a file ending in ".pc" exits in that directory. There are other ways to do this by piping the results to wc -l, but that spawns additional subshells that are best avoided.

(also note that Linux and Mac have files ending in ".pc" for use by pkg-config used when building programs from source -- they should not conflict with your files -- but be aware they exists in case you start chasing why weird ".pc" files are found)

After all tests are performed, the path is trimmed from the current ".7" filename storing just the filename in file7. The file7 variabli is then used in your pc_script command (which should also include the full path to the script if not in you PATH). After the pc_script is run [ -s "result.h5" ] is used to verify that result.h5 exists and is non-empty before moving that file to your Result_Folder location.

That should get you started. Using find to locate all .7 files is a simple way to let the tool designed to find the files for you do its job -- rather than trying to hand-roll your own solution. That way you only have to concentrate on what should be done for each file found. (note: I don't have pc_script or the files, so I have not testes this end-to-end, but it should be very close if not right-on-the-money)

There is nothing wrong in writing your own routine, but using find eliminates a lot of area where bugs can hide in your own solution.

Let me know if you have further questions.



Related Topics



Leave a reply



Submit