在bash中获取文件的父目录

时间:2016-11-20 02:38:50

标签: linux bash shell sh

如何获取文件的父目录?

我希望它对所有类型的名称都是安全的:

.
..
path/to/my/file
/absolute/path/to/my/file
'-rf --no-preserve-root whatever'/test.zip
(symbolic links)
`'"`'{(})

我更感兴趣的是获取文件系统上的规范位置,而不是遍历文件名中指定的路径。

请注意,与此问题存在类似问题,但没有一个问题集中在正确性,相对/绝对路径和"不安全"名称:

[1] bash get the parent directory of current directory

[2] Retrieve parent directory of script

[3] bash filepath to parent directory of file

2 个答案:

答案 0 :(得分:6)

真正安全的解决方案:

parent_dir="$(dirname -- "$(realpath -- "$file_name")")"

如果您的系统没有realpath但有readlink,那么这应该有效:

parent_dir="$(dirname -- "$(readlink -f -- "$file_name")")"

答案 1 :(得分:1)

Bash的cd命令有几个有趣但很少使用的选项,-P-L

   cd [-L|[-P [-e]] [-@]] [dir]
      ...    The  -P  option  causes  cd to use the physical directory
      structure by resolving symbolic links while traversing  dir  and
      before processing instances of .. in dir (see also the -P option
      to the set builtin command); the -L option forces symbolic links
      to  be followed by resolving the link after processing instances
      of .. in dir. ...

所以......如果您正在寻找当前工作目录的文件系统中的物理位置,您可以使用以下内容:

realwd="$(cd -P .; pwd)"

在您的评论中,您提到您正在寻找包含文件的目录的父目录 - 因此,如果路径为/foo/bar/baz/filename,您就是&#39 ; d正在寻找/foo/bar

为了得到这个,我建议cd -P和参数扩展的组合。由于您知道/字符永远不会作为文件名的一部分存在,因此以下内容可能对您有用:

grandparent() {
    local realdir="$(cd -P "${1%/*}"; pwd)"
    echo "${realdir%/*}"
}

这可以通过cd -P使用"得到"文件的物理位置,然后参数扩展以去除路径中的最后一项。

$ mkdir -p one/two/three
$ touch one/two/three/foo
$ ln -s one/two/three bar
$ ls -l bar
lrwxr-xr-x  1 ghoti  wheel  13 Nov 19 23:05 bar -> one/two/three
$ grandparent bar/foo
/usr/home/ghoti/tmp6/one/two