Determine the path of the executing BASH script
For the relative path (i.e. the direct equivalent of Windows' %~dp0
):
MY_PATH=$(dirname "$0")
echo "$MY_PATH"
For the absolute, normalized path:
MY_PATH=$(dirname "$0") # relative
MY_PATH=$(cd "$MY_PATH" && pwd) # absolutized and normalized
if [[ -z "$MY_PATH" ]] ; then
# error; for some reason, the path is not accessible
# to the script (e.g. permissions re-evaled after suid)
exit 1 # fail
fi
echo "$MY_PATH"
Reliable way for a Bash script to get the full path to itself
Here's what I've come up with (edit: plus some tweaks provided by sfstewman, levigroker, Kyle Strand, and Rob Kennedy), that seems to mostly fit my "better" criteria:
SCRIPTPATH="$( cd -- "$(dirname "$0")" >/dev/null 2>&1 ; pwd -P )"
That SCRIPTPATH
line seems particularly roundabout, but we need it rather than SCRIPTPATH=`pwd`
in order to properly handle spaces and symlinks.
The inclusion of output redirection (>/dev/null 2>&1
) handles the rare(?) case where cd
might produce output that would interfere with the surrounding $( ... )
capture. (Such as cd
being overridden to also ls
a directory after switching to it.)
Note also that esoteric situations, such as executing a script that isn't coming from a file in an accessible file system at all (which is perfectly possible), is not catered to there (or in any of the other answers I've seen).
The --
after cd
and before "$0"
are in case the directory starts with a -
.
Get the path of current script
In RStudio, you can get the path to the file currently shown in the source pane using
rstudioapi::getSourceEditorContext()$path
If you only want the directory, use
dirname(rstudioapi::getSourceEditorContext()$path)
If you want the name of the file that's been run by source(filename)
, that's a little harder. You need to look for the variable srcfile
somewhere back in the stack. How far back depends on how you write things, but it's around 4 steps back: for example,
fi <- tempfile()
writeLines("f()", fi)
f <- function() print(sys.frame(-4)$srcfile)
source(fi)
fi
should print the same thing on the last two lines.
Unix shell script find out which directory the script file resides?
In Bash, you should get what you need like this:
#!/usr/bin/env bash
BASEDIR=$(dirname "$0")
echo "$BASEDIR"
How do I get the directory where a Bash script is located from within the script itself?
#!/usr/bin/env bash
SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )
is a useful one-liner which will give you the full directory name of the script no matter where it is being called from.
It will work as long as the last component of the path used to find the script is not a symlink (directory links are OK). If you also want to resolve any links to the script itself, you need a multi-line solution:
#!/usr/bin/env bash
SOURCE=${BASH_SOURCE[0]}
while [ -L "$SOURCE" ]; do # resolve $SOURCE until the file is no longer a symlink
DIR=$( cd -P "$( dirname "$SOURCE" )" >/dev/null 2>&1 && pwd )
SOURCE=$(readlink "$SOURCE")
[[ $SOURCE != /* ]] && SOURCE=$DIR/$SOURCE # if $SOURCE was a relative symlink, we need to resolve it relative to the path where the symlink file was located
done
DIR=$( cd -P "$( dirname "$SOURCE" )" >/dev/null 2>&1 && pwd )
This last one will work with any combination of aliases, source
, bash -c
, symlinks, etc.
Beware: if you cd
to a different directory before running this snippet, the result may be incorrect!
Also, watch out for $CDPATH
gotchas, and stderr output side effects if the user has smartly overridden cd to redirect output to stderr instead (including escape sequences, such as when calling update_terminal_cwd >&2
on Mac). Adding >/dev/null 2>&1
at the end of your cd
command will take care of both possibilities.
To understand how it works, try running this more verbose form:
#!/usr/bin/env bash
SOURCE=${BASH_SOURCE[0]}
while [ -L "$SOURCE" ]; do # resolve $SOURCE until the file is no longer a symlink
TARGET=$(readlink "$SOURCE")
if [[ $TARGET == /* ]]; then
echo "SOURCE '$SOURCE' is an absolute symlink to '$TARGET'"
SOURCE=$TARGET
else
DIR=$( dirname "$SOURCE" )
echo "SOURCE '$SOURCE' is a relative symlink to '$TARGET' (relative to '$DIR')"
SOURCE=$DIR/$TARGET # if $SOURCE was a relative symlink, we need to resolve it relative to the path where the symlink file was located
fi
done
echo "SOURCE is '$SOURCE'"
RDIR=$( dirname "$SOURCE" )
DIR=$( cd -P "$( dirname "$SOURCE" )" >/dev/null 2>&1 && pwd )
if [ "$DIR" != "$RDIR" ]; then
echo "DIR '$RDIR' resolves to '$DIR'"
fi
echo "DIR is '$DIR'"
And it will print something like:
SOURCE './scriptdir.sh' is a relative symlink to 'sym2/scriptdir.sh' (relative to '.')
SOURCE is './sym2/scriptdir.sh'
DIR './sym2' resolves to '/home/ubuntu/dotfiles/fo fo/real/real1/real2'
DIR is '/home/ubuntu/dotfiles/fo fo/real/real1/real2'
What's the best way to determine the location of the current PowerShell script?
PowerShell 3+
# This is an automatic variable set to the current file's/module's directory
$PSScriptRoot
PowerShell 2
Prior to PowerShell 3, there was not a better way than querying theMyInvocation.MyCommand.Definition
property for general scripts. I had the following line at the top of essentially every PowerShell script I had:
$scriptPath = split-path -parent $MyInvocation.MyCommand.Definition
How can I find script's directory?
You need to call os.path.realpath
on __file__
, so that when __file__
is a filename without the path you still get the dir path:
import os
print(os.path.dirname(os.path.realpath(__file__)))
How to get the directory of the executing script in R?
Collecting resources from multiple questions in SO, I came up with the following solution, that seems to work with multiple calling conventions:
library(base)
library(rstudioapi)
get_directory <- function() {
args <- commandArgs(trailingOnly = FALSE)
file <- "--file="
rstudio <- "RStudio"
match <- grep(rstudio, args)
if (length(match) > 0) {
return(dirname(rstudioapi::getSourceEditorContext()$path))
} else {
match <- grep(file, args)
if (length(match) > 0) {
return(dirname(normalizePath(sub(file, "", args[match]))))
} else {
return(dirname(normalizePath(sys.frames()[[1]]$ofile)))
}
}
}
Which later I can use as:
path <- paste(get_directory(), "/output/", filename, sep = "")
Related Topics
Delete Rows That Exist in Another Data Frame
Selecting Multiple Odd or Even Columns/Rows for Dataframe
R Collapse Multiple Rows into 1 Row - Same Columns
Divide All Columns by the Value from the 2Nd Column - Apply for All Rows
R: Pulling Data from One Column to Create New Columns
Concatenate String Columns and Order in Alphabetical Order
How to Show Code But Hide Output in Rmarkdown
How to Change the Default Colors in Plotly Chart
Removing All Empty Columns and Rows in Data.Frame When Rows Don't Go Away
Add Column Values Based on Other Columns in Data Frame Using for and If
Adding Value from One Data.Frame to Another Data.Frame by Matching a Variable
How to Convert Only Some Positive Numbers to Negative Numbers (Conditional Recoding)
Dplyr Conditional Summarise Function
How to Add a Suffix (Or Prefix) Elements of an Existing List
Converting Data Frame into a List of Lists in R
Conditionally Replace Values of Subset of Rows With Column Name in R Using Only Tidy
How to Spread Repeated Measures of Multiple Variables into Wide Format