解决破碎的符号链接

时间:2017-07-10 22:31:03

标签: linux file go symlink

我希望我的Go程序能够解决一些符号链接的目标。唯一的麻烦是这些符号链接将指向实际不存在的目标,这很好,因为我之后做了一些文件路径操作。这甚至可能吗?如果我执行" readlink -f",我会在退出代码1中得到一个零结果。

// path is the filepath of a symlink
// this symlink will most likely be pointing to a non-existent file/location
// this is fine and is handled elsewhere
func handleSymlink(path *string) (bool, error) {
    f, err := os.Lstat(*path)
    if err != nil {
        return false, err
    }

    // if f is nil, then this is not a symlink
    if f == nil {
        return false, nil
    }

    ln, err := os.Readlink(*path)
    //ln, err := filepath.EvalSymlinks(*path)

    // ignore IsNotExist errors...this is expected
    if !os.IsNotExist(err) {
        return false, err
    }

    path = &ln
    return true, nil 
} 

2 个答案:

答案 0 :(得分:0)

使用os.Lstat func:

  

Lstat返回描述指定文件的FileInfo。如果文件是符号链接,则返回的FileInfo描述符号链接。 Lstat不会尝试关注该链接。如果有错误,则其类型为* PathError。

因此,您可以使用返回的os.FileInfo值来检查它是否为符号链接。

fileInfo.Mode()&os.ModeSymlink != 0

此时你知道给定的路径是符号链接。

如果您想获得指向的符号链接的实际路径,请使用

filepath.EvalSymlinks(path)

您的更新代码:

func handleSymlink(path *string) (bool, error) {
    fileInfo, err := os.Lstat(*path)
    if os.IsNotExist(err) || err != nil {
        return false, err
    }

    // Check path is symlink or not
    if fileInfo.Mode()&os.ModeSymlink != 0 {
        actualPath, err := filepath.EvalSymlinks(*path)
        if err != nil {
            // Extract actual path from error msg
            apath := strings.Split(err.Error(), ":")[0]
            *path = strings.Split(apath, " ")[1]
            return false, err
        }
        *path = actualPath
        return true, nil
    }

    return false, nil
}

func main() {
    path := "/Users/jeeva/test1"
    result, err := handleSymlink(&path)
    fmt.Println("Error:", err)
    fmt.Println("Result:", result)
    fmt.Println("Actual Path:", path)
}

我们说我们有以下路径:

/Users/jeeva/test1 (symlink, pointing to /Users/jeeva/actualpath)
/Users/jeeva/actualpath
/Users/jeeva/actualpath2

如果存在给定路径并且它是符号链接:

#Input:
/Users/jeeva/test1

#Output:
Error: <nil>
Result: true
Actual Path: /Users/jeeva/actualpath

如果给定路径不存在:

#Input:
/Users/jeeva/test1

#Output:
Error lstat /Users/jeeva/notexists: no such file or directory
Result: false
Actual Path: /Users/jeeva/notexists

如果给定路径存在且它不是符号链接:

#Input:
/Users/jeeva/actualpath2

#Output:
Error <nil>
Result: false
Actual Path: /Users/jeeva/actualpath2

答案 1 :(得分:0)

你想要Unix系统调用readlink,它在Go中导出为os.Readlink。它读取符号链接的内容,不进行进一步处理 - 不检查是否存在或递归处理。

target, err := os.Readlink("test1")