简体   繁体   English

解决断开的符号链接

[英]Resolving broken symbolic links

I want my Go program to resolve the targets of a few symlinks. 我希望Go程序解决一些符号链接的目标。 The only trouble is these symlinks will be pointing to destinations that do not actually exist, which is fine because I do some filepath manipulations afterwards. 唯一的麻烦是这些符号链接将指向实际不存在的目标,这很好,因为之后我会进行一些文件路径操作。 Is this even possible? 这有可能吗? If I do a "readlink -f ", I do get a nil result with exit code 1. 如果我执行“ 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 
} 

Use os.Lstat func: 使用os.Lstat函数:

Lstat returns a FileInfo describing the named file. Lstat返回描述命名文件的FileInfo。 If the file is a symbolic link, the returned FileInfo describes the symbolic link. 如果文件是符号链接,则返回的FileInfo将描述符号链接。 Lstat makes no attempt to follow the link. Lstat不会尝试跟随该链接。 If there is an error, it will be of type *PathError. 如果有错误,它将是* PathError类型。

So you can use returned os.FileInfo value to check whether it's a symlink or not. 因此,您可以使用返回的os.FileInfo值来检查它是否是符号链接。

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

At this point you know that given path is symlink. 至此,您知道给定的路径是符号链接。


If you would like to get the actual path of symlink that is pointing to, use 如果您想获取指向符号链接的实际路径,请使用

filepath.EvalSymlinks(path)

Your updated code: 您更新的代码:

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)
}

Let's say we have following paths: 假设我们有以下路径:

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

If given path exists and it's a symlink: 如果给定路径存在并且是符号链接:

#Input:
/Users/jeeva/test1

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

If given path is not exists: 如果给定路径不存在:

#Input:
/Users/jeeva/test1

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

If given path is exists and it's not a symlink: 如果给定路径存在并且不是符号链接:

#Input:
/Users/jeeva/actualpath2

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

You want the Unix system call readlink , which is exported in Go as os.Readlink . 您需要Unix系统调用readlink ,它在Go中作为os.Readlink导出。 It reads the content of a symlink and does no further processing — no checking for existence or recursive processing. 它读取符号链接的内容,不做进一步处理-不检查是否存在或进行递归处理。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM