基本上我需要运行与shell脚本文件位置相关的路径脚本,我如何将当前目录更改为脚本文件所在的相同目录?


当前回答

让我们把它变成一个POSIX在线程序:

a="/$0"; a="${a%/*}"; a="${a:-.}"; a="${a##/}/"; BINDIR=$(cd "$a"; pwd)

在包括BSD在内的许多兼容bourne的shell上进行了测试。

据我所知,我是作者,我把它放到了公共领域。更多信息见: https://www.bublina.eu.org/posts/2017-05-11-posix_shell_dirname_replacement/

其他回答

在Bash中,你应该像这样得到你需要的东西:

#!/usr/bin/env bash

BASEDIR=$(dirname "$0")
echo "$BASEDIR"

So many answers, all plausible, each with pro's and con's & slightly differeing objectives (which should probably be stated for each). Here's another solution that meets a primary objective of both being clear and working across all systems, on all bash (no assumptions about bash versions, or readlink or pwd options), and reasonably does what you'd expect to happen (eg, resolving symlinks is an interesting problem, but isn't usually what you actually want), handle edge cases like spaces in paths, etc., ignores any errors and uses a sane default if there are any issues.

每个组件都存储在一个单独的变量中,您可以单独使用:

# script path, filename, directory
PROG_PATH=${BASH_SOURCE[0]}      # this script's name
PROG_NAME=${PROG_PATH##*/}       # basename of script (strip path)
PROG_DIR="$(cd "$(dirname "${PROG_PATH:-$PWD}")" 2>/dev/null 1>&2 && pwd)"

对于tcsh,您可以使用:h变量修饰符来检索路径。

需要注意的是,如果脚本作为tcsh myscript执行。Csh,那么您将只获得脚本名称。一个解决方法是验证路径,如下所示。

#!/bin/tcsh

set SCRIPT_PATH = $0:h
if ( $SCRIPT_PATH == $0 ) then
        set SCRIPT_PATH = "."
endif

$SCRIPT_PATH/compile.csh > $SCRIPT_PATH/results.txt

关于变量修饰语的更多信息可以在https://learnxinyminutes.com/docs/tcsh/上找到

灵感来自blueyed的回答

read < <(readlink -f $0 | xargs dirname)
cd $REPLY

我发现的最有效的方法之一是

#!/bin/sh
relative_dir=`perl -e 'use Cwd "realpath";$pwd = realpath(shift); $pwd =~ s/\/[^\/]*$//; print $pwd' $0`
cd $relative_dir

使用符号链接工作,并为我的许多同事工作,无论他们选择的shell类型