我编写了一个Bash脚本,该脚本以输入文件作为参数并读取它。
该文件包含一些相对于其位置的路径,指向其他文件。
我希望该脚本能够进入包含输入文件的文件夹,以执行后续命令。
在Linux中,如何从输入文件获取文件夹(仅文件夹)?
要获取完整路径,请使用:
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
的文件的链接。
readlink -f
在 OS X 上无法使用。 - Emil Sitbrew install coreutils
来获取它。https://dev59.com/UnNA5IYBdhLWcg3wL62x#4031502。 - mpettis${1%/*}
或 ${1##*/}
作为 dirname
和 basename
的替代品。前者对于简单文件名会出错(例如,dirname foo.bar
应该返回 .
),而后者对于以斜杆结尾的目录也会出错(例如,basename /foo/bar/
应该返回 bar
)。 - Camilo Martinbasename
/dirname
不是内置函数),他们一开始会看到它正常工作,但在未来某个时刻突然崩溃,原因似乎没有什么好的理由。我建议避免将其作为选择,或者声明它并不是一个完全可靠的替代品。 - Camilo Martin这将适用于文件和文件夹:
absPath(){
if [[ -d "$1" ]]; then
cd "$1"
echo "$(pwd -P)"
else
cd "$(dirname "$1")"
echo "$(pwd -P)/$(basename "$1")"
fi
}
$cat abs.sh
#!/bin/bash
echo "$(cd "$(dirname "$1")"; pwd -P)"
一些解释:
"$1"
dirname "$1"
cd "$(dirname "$1");
进入这个相对目录pwd -P
并获取绝对路径。 -P
选项将避免符号链接echo
输出它然后运行您的脚本:
abs.sh your_file.txt
试试我们在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。
以上答案的问题出在输入带有 "./" 的文件,例如 "./my-file.txt"
解决方法(众多之一):
myfile="./somefile.txt"
FOLDER="$(dirname $(readlink -f "${ARG}"))"
echo ${FOLDER}
我一直在使用在Linux上可用的readlink -f命令。
所以
FULL_PATH=$(readlink -f filename)
DIR=$(dirname $FULL_PATH)
PWD=$(pwd)
cd $DIR
#<do more work>
cd $PWD
PWD
在Bash中已经存在,并且它的值实际上是当前目录吗?另外,请多使用引号。 - gniourf_gniourf