I have a shell script in my local bin folder so I can run it anywhere. In this script, I perform search and replace commands using sed.
When I run that script, I set $PWD as argument of the script so the sed commands work on the files in the folder where I started the script and not in the bin folder.
What do I have to adapt such that my script is always in the path I am calling from without using the workaround applying $PWD as argument?
Many thanks in advance!
As written by Aaron:
You don't need to, it'll do that by default. What you need to be careful about is to avoid paths relative to the script's location : those will need to be made absolute (or will require a cd) to work when you're calling the script from another location
Related
I have a c5 project with a directory C5PROJECTDIR it has a bin directory. Is there a way (without adding C5PROJECTDIR/bin to $PATH) to access commands from any other subdirectory of C5PROJECTDIR?
For example:
There is an x command located here: C5PROJECTDIR/bin/x.
I want to run this command from a bash script from C5PROJECTDIR/packages/some-other-dir.
UPDATE: The sub directory can be more or less deeper in the tree...
How can it be possible?
There are a few ways:
Use relative paths:
Essentially call the binary directly with its path, but relative to the current script. If your script is located in /home/user/foo/C5PROJECTDIR/packages/somedir/script, then you call the script relatively:
#!/usr/bin/env bash
../../bin/x
The problem with this method is maintainability. Imagine you want to move your script to /home/user/foo/C5PROJECTDIR/packages/scripts, then you would have to update all your scripts.
Use a shell variable:
Instead of relative paths, you can define a variable PROJECTHOME which contains the base value.
#!/usr/bin/env bash
PROJECTHOME=/home/user/foo/C5PROJECTDIR
$PROJECTHOME/bin/x
This generally solves most problems unless you move project location from /home/user/foo/C5PROJECTDIR to /home/user/random-dir. But this can be solved with a simple sed command that searches for the line /home/user/foo/C5PROJECTDIR and replaces it.
PATH variable only make things easier.
You able to run any commands with absolute path like /bin/echo or /home/jon/myscript. Relative path works as well ~/../../bin/ls.
Script have its own PATH variable, so you can add the desired location to PATH in your script if you like.
Apart from this you have to deal with permissions.
The user that have script executed by, must have execute permission on the x script.
To find and execute command:
find C5PROJECTDIR -type f -executable -name "x" -exec {} \;
Find's must be strict to match only one command else it will execute all that it fund. You cannot have script with the same name under C5PROJECTDIR in this case.
From security point of view. I do not recommend this, as anyone can put an executable file under C5PROJECTDIR with a name used in the script. things can go nasty.
(First post, be gentle.)
In a bash script, I am using:
#!/bin/bash
baseDir=$(dirname "$BASH_SOURCE")
I have saved the script as /path/to/location/script.command, so that a double-click in Finder in macOS will execute the script.
I have created symlinks to that script from multiple other locations, but no matter the location, $baseDir always returns as /path/to/location.
However if I save the script as /path/to/location/script.sh and create symlinks to that in, for example, /path/for/symlink, then $baseDir returns as my desired outcome, /path/for/symlink.
My assumption is that symlinking a .sh will always run said script from the location of the symlink, whereas symlinking a .command will always run said script from the location of the linked script.
Unfortunately, this solution won't work because I need to resolve symlinks, and this solution won't work because $0 returns the same as $BASH_SOURCE.
By recommendation of Charles below, I've scoured this FAQ, but unless I'm missing something, all the suggestions would require one of $0, $BASH_SOURCE, or PWD to return the path to the symlink, not the path to the linked script.
Is there any way around this?
I am very new to bash and using .sh files. I am trying to run the program aescrypt by calling it in a .sh file as follows (aescrypt is in the same directory as the .sh file) :
./aescrypt -e -p password file.txt
It throws the following error:
./aescrypt no such file or directory
Am I doing it wrong?
ps- I realy don't want to add it to the PATH variable as I will be using this on more than one computer that resets every day.
The location of the script is irrelevant. The thing that matters is the working directory of the process executing the script. The simplest solution really is to add aescrypt to a standard location like /bin or /usr/bin. If neither of those is acceptable, perhaps /usr/local/bin is an option. Otherwise, just use the full path of aescrypt in your script. Either hard code it, or if it is in the same directory as the script, try:
$(dirname $0)/aescrypt ...
(Note that hardcoding is more reliable, but less flexible. If you move the executable, the script will break. But using dirname will break if the script changes directory during execution.)
how about if you call the program like ./aescrypt.sh, thats the way to call an .sh programm througt the terminal
First off all, you have also to change the permissions of the file to make it executable, the way to make that is to write in the terminal, the command:
sudo chmod 765 aescrypt.sh
For that you have to be located where the file is
In order for me to run a .exe or a .sh in Cyqwin, I have to put a ./ at the beginning of my line. Is there a way for me to change this so that isn't necessary? This is causing problems when I try and run a test script and it can't find files that are right in the directory I'm working in.
The reason you must use a './' is to specifically tell the shell what file you are trying to execute. Without the leading './', your $PATH environment variable is searched. You can try adding the directories with scripts and executables you commonly use to your $PATH if you'd like. Alternatively, you can add the current directory (.) to your $PATH, but this is a Very Bad Idea as it can lead to unintentional executions.
From the cygwin environment variables doc:
The PATH environment variable is used by Cygwin applications as a list
of directories to search for executable files to run. This environment
variable is converted from Windows format (e.g.
C:\Windows\system32;C:\Windows) to UNIX format (e.g.,
/cygdrive/c/Windows/system32:/cygdrive/c/Windows) when a Cygwin
process first starts. Set it so that it contains at least the
x:\cygwin\bin directory where "x:\cygwin is the "root" of your cygwin
installation if you wish to use cygwin tools outside of bash.
I am on Mac's OS 10.6, and I am trying to learn a thing or two about shell scripting. I understand how to save a shell script and make it executable, but I am wondering what I can do or where I can save the file to make it global (that is, accessible no matter what folder I am in).
For example, if I save a .sh file in the /Users/username/ directory and make it executable, I can only execute that script in that specific directory. If I navigate to /Users/username/Downloads, for example, I can't execute the script.
Also, any suggestions of resources for learning more about shell scripting would be helpful. Thanks
/usr/local/bin would be the most appropriate location. Mac OS X has it in the PATH by default
There are two ways to do it -
Put your script in usr/local/bin and make sure it is executable(chmod +x my_script)(This is already set in the path, you can check by doing an echo $PATH)
Create a folder in your home directory called bin. (For your personal scripts)
cd ~ (Takes you to your home directory)
mkdir bin (create a bin folder)
vim .bash_profile (to set path environment variable)
export PATH=~/bin:$PATH (Press i then add this line and then do esc and type :wq)
Now you can just type the name of your script and run it from anywhere you want.
** NOTE: If you want to run the script with a shortened command rather than typing your entire filename, add the following to your .bash_profile:
alias myscript='my_script.sh'
Then you can run the script by simply typing myscript. (you can sub in whatever alias you'd like)
Traditionally, such scripts either go in ~/bin (ie: the bin directory in your home directory) or /usr/local/bin/ The former means the script will only work for you, the latter is for scripts you want anybody on the system to be able to run.
If you put it in ~/bin, you may need to add that to your PATH environment variable. /usr/local/bin should already be on the path.
In mac operating system
Open bash ~/.bashrc file.
add path of your script in your bashrc file , using
export PATH="$PATH:/Users/sher.mohammad/Office/practice/practiceShell"
Open your ~./bash_profile file and add [[ -s ~/.bashrc ]] && source ~/.bashrc
open new terminal window
Now whenever you will open your terminal your script will be loaded
This one is super easy if you are familiar with your bashrc file! This will entirely use just your .bashrc file and takes 2 seconds to accomplish.
(I use Arch Linux Manjaro so I use .bashrc located in my home directory)
The code to be placed in your .bashrc file:
# Simple bashrc method to launch anything in terminal from any directory
YOURCOMMAND () {
cd /path/to/directory/containing/your/script/ && ./YOURSCRIPT
}
As you can see, first you use the simple 'cd' command and give it the directory of the scripts location, then use '&&' so that you can make the next command executed right after, and finally open your script just as you would normally! Super easy and saved right in your .bash file! :)
Hope I've helped someone!
Sincerely,
AnonymousX
On using bash shell, write that script as function and then put it to the .bashrc or source the file which containing that function by "source file_name"
Now execute the script by function call in the shell.
Either saving it in /usr/bin (or any other directory present in PATH) or editing PATH to include the directory you saved it in will basically make it run in any directory.
from the working directory of 'script.sh'" mv [script.sh] /usr/local/bin"( not tested but seems to be the least complex way IMO.)
You should put it in the global executable directory on your machine. I think that would usually be /usr/bin on Unix-based operating systems (this would however most often require super user privileges on that machine).
You could also put it in any other directory that is in the $PATH environment variable, although it would only work for those users who have that directory in that variable.
You can find the value of $PATH by typing echo $PATH in a shell. The directories are separated by :.