95

我编写了一个 bash 脚本,它将输入文件作为参数并读取它。
该文件包含一些路径(相对于其位置)到所使用的其他文件。

我希望脚本转到包含输入文件的文件夹,以执行进一步的命令。

那么,如何从输入文件中获取文件夹(并且只是文件夹)?(在 Linux 中。)

4

7 回答 7

166

要获得完整路径,请使用:

readlink -f relative/path/to/file

要获取文件的目录:

dirname relative/path/to/file

您也可以将两者结合起来:

dirname $(readlink -f relative/path/to/file)

如果readlink -f在您的系统上不可用,您可以使用此*

function myreadlink() {
  (
  cd "$(dirname $1)"         # or  cd "${1%/*}"
  echo "$PWD/$(basename $1)" # or  echo "$PWD/${1##*/}"
  )
}

请注意,如果您只需要移动到指定为相对路径的文件的目录,则不需要知道绝对路径,相对路径是完全合法的,因此只需使用:

cd $(dirname relative/path/to/file)

如果您希望(在脚本运行时)返回到原始路径,请使用pushd代替cd,并popd在完成后使用。


*虽然myreadlink以上在这个问题的背景下已经足够好,但相对于readlink上面建议的工具,它有一些限制。例如,它没有正确地跟随指向具有不同basename.

于 2013-07-10T17:30:16.783 回答
23

看看realpath哪些在GNU/LinuxFreeBSDNetBSD上可用,但在 OpenBSD 6.8 上不可用。我使用类似的东西:

CONTAININGDIR=$(realpath ${FILEPATH%/*})

做你想做的事。

于 2013-07-10T17:32:23.703 回答
6

这将适用于文件和文件夹:

absPath(){
    if [[ -d "$1" ]]; then
        cd "$1"
        echo "$(pwd -P)"
    else 
        cd "$(dirname "$1")"
        echo "$(pwd -P)/$(basename "$1")"
    fi
}
于 2015-08-06T16:50:16.733 回答
5
$cat abs.sh
#!/bin/bash
echo "$(cd "$(dirname "$1")"; pwd -P)"

一些解释:

  1. 此脚本获取相对路径作为参数"$1"
  2. 然后我们得到该路径的dirname部分(您可以将 dir 或 file 传递给此脚本):dirname "$1"
  3. 然后我们cd "$(dirname "$1");进入这个相对目录
  4. pwd -P并获得绝对路径。该-P选项将避免符号链接
  5. 作为最后一步,echo我们

然后运行你的脚本:

abs.sh your_file.txt
于 2016-12-08T18:34:05.140 回答
1

在 GitHub 上试用我们新的 Bash 库产品realpath-lib,我们已将其提供给社区,供免费且不受阻碍地使用。它干净、简单且有据可查,因此非常值得学习。你可以做:

get_realpath <absolute|relative|symlink|local file path>

这个函数是库的核心:

if [[ -f "$1" ]]
then
    # file *must* exist
    if cd "$(echo "${1%/*}")" &>/dev/null
    then
        # file *may* not be local
        # exception is ./file.ext
        # try 'cd .; cd -;' *works!*
        local tmppwd="$PWD"
        cd - &>/dev/null
    else
        # file *must* be local
        local tmppwd="$PWD"
    fi
else
    # file *cannot* exist
    return 1 # failure
fi

# reassemble realpath
echo "$tmppwd"/"${1##*/}"
return 0 # success

}

它是 Bash 4+,不需要任何依赖项,还提供 get_dirname、get_filename、get_stemname 和 validate_path。

于 2013-10-02T17:05:12.973 回答
0

上述答案的问题来自带有“./”的文件输入,例如“./my-file.txt”

解决方法(许多):

    myfile="./somefile.txt"
    FOLDER="$(dirname $(readlink -f "${ARG}"))"
    echo ${FOLDER}
于 2014-07-24T17:35:50.647 回答
-1

我一直在使用 readlink -f 在 linux 上工作

所以

FULL_PATH=$(readlink -f filename)
DIR=$(dirname $FULL_PATH)

PWD=$(pwd)

cd $DIR

#<do more work>

cd $PWD
于 2013-07-10T17:31:37.553 回答