我如何找到一个Bash脚本位于该脚本内部的目录的路径?
我想用Bash脚本作为另一个应用程序的启动器,我想将工作目录更改为Bash脚本所在的目录,所以我可以在该目录中的文件上运行,如下:
$ ./application
我如何找到一个Bash脚本位于该脚本内部的目录的路径?
我想用Bash脚本作为另一个应用程序的启动器,我想将工作目录更改为Bash脚本所在的目录,所以我可以在该目录中的文件上运行,如下:
$ ./application
当前回答
這是我多年來創造的,用作我的Bash寫作的標題:
## BASE BRAIN - Get where you're from and who you are.
MYPID=$$
ORIGINAL_DIR="$(pwd)" # This is not a hot air balloon ride..
fa="$0" # First Assumption
ta= # Temporary Assumption
wa= # Weighed Assumption
while true; do
[ "${fa:0:1}" = "/" ] && wa=$0 && break
[ "${fa:0:2}" = "./" ] && ta="${ORIGINAL_DIR}/${fa:2}" && [ -e "$ta" ] && wa="$ta" && break
ta="${ORIGINAL_DIR}/${fa}" && [ -e "$ta" ] && wa="$ta" && break
done
SW="$wa"
SWDIR="$(dirname "$wa")"
SWBIN="$(basename "$wa")"
unset ta fa wa
( [ ! -e "$SWDIR/$SWBIN" ] || [ -z "$SW" ] ) && echo "I could not find my way around :( possible bug in the TOP script" && exit 1
此时此刻,您的变量 SW、SWDIR 和 SWBIN 包含您需要的内容。
其他回答
您可以做到这一点,只需将脚本名称($0)与 realpath 和/或 dirname 相结合,它适用于 Bash 和 Shell。
#!/usr/bin/env bash
RELATIVE_PATH="${0}"
RELATIVE_DIR_PATH="$(dirname "${0}")"
FULL_DIR_PATH="$(realpath "${0}" | xargs dirname)"
FULL_PATH="$(realpath "${0}")"
echo "RELATIVE_PATH->${RELATIVE_PATH}<-"
echo "RELATIVE_DIR_PATH->${RELATIVE_DIR_PATH}<-"
echo "FULL_DIR_PATH->${FULL_DIR_PATH}<-"
echo "FULL_PATH->${FULL_PATH}<-"
结果将是这样的:
# RELATIVE_PATH->./bin/startup.sh<-
# RELATIVE_DIR_PATH->./bin<-
# FULL_DIR_PATH->/opt/my_app/bin<-
# FULL_PATH->/opt/my_app/bin/startup.sh<-
$0 是脚本本身的名称
4.4 特殊变量类型
例如:LozanoMatheus/get_script_paths.sh
查看下面的测试与奇怪的目录名称。
要将工作目录更改为Bash脚本的位置,您应该尝试这个简单的,测试和验证的Shellcheck解决方案:
#!/bin/bash --
cd "$(dirname "${0}")"/. || exit 2
测试:
$ ls
application
$ mkdir "$(printf "\1\2\3\4\5\6\7\10\11\12\13\14\15\16\17\20\21\22\23\24\25\26\27\30\31\32\33\34\35\36\37\40\41\42\43\44\45\46\47testdir" "")"
$ mv application *testdir
$ ln -s *testdir "$(printf "\1\2\3\4\5\6\7\10\11\12\13\14\15\16\17\20\21\22\23\24\25\26\27\30\31\32\33\34\35\36\37\40\41\42\43\44\45\46\47symlink" "")"
$ ls -lb
total 4
lrwxrwxrwx 1 jay stacko 46 Mar 30 20:44 \001\002\003\004\005\006\a\b\t\n\v\f\r\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037\ !"#$%&'symlink -> \001\002\003\004\005\006\a\b\t\n\v\f\r\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037\ !"#$%&'testdir
drwxr-xr-x 2 jay stacko 4096 Mar 30 20:44 \001\002\003\004\005\006\a\b\t\n\v\f\r\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037\ !"#$%&'testdir
$ *testdir/application && printf "SUCCESS\n" ""
SUCCESS
$ *symlink/application && printf "SUCCESS\n" ""
SUCCESS
下面将返回剧本的当前目录
工作,如果它是源,或者不源工作,如果运行在当前的目录,或某些其他目录.工作,如果相对目录被使用.工作与 bash,不确定其他<unk>。
/tmp/a/b/c $ . ./test.sh
/tmp/a/b/c
/tmp/a/b/c $ . /tmp/a/b/c/test.sh
/tmp/a/b/c
/tmp/a/b/c $ ./test.sh
/tmp/a/b/c
/tmp/a/b/c $ /tmp/a/b/c/test.sh
/tmp/a/b/c
/tmp/a/b/c $ cd
~ $ . /tmp/a/b/c/test.sh
/tmp/a/b/c
~ $ . ../../tmp/a/b/c/test.sh
/tmp/a/b/c
~ $ /tmp/a/b/c/test.sh
/tmp/a/b/c
~ $ ../../tmp/a/b/c/test.sh
/tmp/a/b/c
测试.sh
#!/usr/bin/env bash
# snagged from: https://stackoverflow.com/a/51264222/26510
function toAbsPath {
local target
target="$1"
if [ "$target" == "." ]; then
echo "$(pwd)"
elif [ "$target" == ".." ]; then
echo "$(dirname "$(pwd)")"
else
echo "$(cd "$(dirname "$1")"; pwd)/$(basename "$1")"
fi
}
function getScriptDir(){
local SOURCED
local RESULT
(return 0 2>/dev/null) && SOURCED=1 || SOURCED=0
if [ "$SOURCED" == "1" ]
then
RESULT=$(dirname "$1")
else
RESULT="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
fi
toAbsPath "$RESULT"
}
SCRIPT_DIR=$(getScriptDir "$0")
echo "$SCRIPT_DIR"
保持简单。
#!/usr/bin/env bash
sourceDir=`pwd`
echo $sourceDir
这种方法的一个好处是,它不涉及Bash本身以外的任何东西,也不会破坏任何底层。
首先,使用模式替代替代不以 / (即相对路径) 以 $ PWD/. 因为我们使用替代替代相匹配的第一个字符为 $ 0,我们也必须添加它回来(${0:0:1} 在替代中)。
现在我们有一个完整的路径到脚本;我们可以通过删除最后的 / 和随后的任何东西(即脚本名称)来获得目录。
#!/bin/bash
BIN=${0/#[!\/]/"$PWD/${0:0:1}"}
DIR=${BIN%/*}
cd "$DIR"
如果您的脚本可以源于而不是执行,您可以将 $0 取代 ${BASH_SOURCE[0]},例如:
BIN=${BASH_SOURCE[0]/#[!\/]/"$PWD/${BASH_SOURCE[0]:0:1}"}
这将为可执行的脚本工作,它更长,但更多。