resolve symlinks in Go

huangapple go评论86阅读模式
英文:

resolve symlinks in Go

问题

你可以使用Go语言的os.Readlink函数来解析符号链接。下面是使用os.Readlink函数修改后的代码:

package main

import (
	"os"
	"fmt"
)

func resolve(p string) (string, error) {
	link, err := os.Readlink(p)
	if err != nil {
		return "", err
	}

	return link, nil
}

func main() {
	resolvedPath, err := resolve("/initrd.img")
	if err != nil {
		fmt.Println("Error resolving symlink:", err)
		return
	}

	fmt.Println(resolvedPath)
}

这样,你就可以使用os.Readlink函数来解析符号链接,而不需要调用外部命令。

英文:

How can I resolve symlinks in Go?

Currently I call readlink -f but I want something more idiomatic.

package main

import (
	"os/exec"
	"fmt"
)

func resolve(p string) string {
	cmd := exec.Command("readlink", "-f", p)
   	out, _ := cmd.Output()

    return (string(out))
}

func main() {
	fmt.Printf(resolve("/initrd.img"))
}

答案1

得分: 39

请注意,我将为您翻译以下内容:

参见 filepath.EvalSymlinks()
>EvalSymlinks 返回在解析任何符号链接后的路径名。如果路径是相对路径,则结果将相对于当前目录,除非其中一个组件是绝对符号链接。

示例

树:

/bin/sh -> bash
/usr/lib/libresolv.so -> ../../lib/libresolv.so.2

os.Readlink()

os.Readlink("/bin/sh") // => bash
os.Readlink("/usr/lib/libresolv.so") //=> ../../lib/libresolv.so.2

filepath.EvalSymlinks()

filepath.EvalSymlinks("/bin/sh") // => /bin/bash
filepath.EvalSymlinks("/usr/lib/libresolv.so") //=> /lib/libresolv-2.20.so

注意:不是绝对路径(cd /bin

 filepath.EvalSymlinks("sh") // => bash
 filepath.EvalSymlinks("/bin/sh") // => /bin/bash

还有一些其他内容

 filepath.EvalSymlinks("/bin/bash") // => /bin/bash
 // 但是
 os.Readlink("/bin/bash") // => 错误:readlink /bin/bash: 无效的参数

示例应用程序 不适用于 playground

英文:

See filepath.EvalSymlinks().
>EvalSymlinks returns the path name after the evaluation of any symbolic links. If path is relative the result will be relative to the current directory, unless one of the components is an absolute symbolic link.

Examples

Tree:

/bin/sh -> bash
/usr/lib/libresolv.so -> ../../lib/libresolv.so.2

os.Readlink()

os.Readlink("/bin/sh") // => bash
os.Readlink("/usr/lib/libresolv.so") //=> ../../lib/libresolv.so.2

filepath.EvalSymlinks()

filepath.EvalSymlinks("/bin/sh") // => /bin/bash
filepath.EvalSymlinks("/usr/lib/libresolv.so") //=> /lib/libresolv-2.20.so

Note: not absolute path (cd /bin)

 filepath.EvalSymlinks("sh") // => bash
 filepath.EvalSymlinks("/bin/sh") // => /bin/bash

And somthing more

 filepath.EvalSymlinks("/bin/bash") // => /bin/bash
 // but
 os.Readlink("/bin/bash") // => error: readlink /bin/bash: invalid argument

Example application not for playground

答案2

得分: 25

使用os.Lstat

func Lstat(name string) (fi FileInfo, err error)

Lstat返回描述指定文件的FileInfo。如果文件是符号链接,则返回的FileInfo描述符号链接。Lstat不会尝试跟踪链接。如果有错误,它将是*PathError类型。

编辑:

然后返回的os.FileInfo只允许您检查'name'是否是链接(fi.Mode() & os.ModeSymlink != 0)。如果是链接,则使用os.Readlink获取指向的文件:

func Readlink(name string) (string, error)

Readlink返回指定符号链接的目标。如果有错误,它将是*PathError类型。

英文:

Use os.Lstat:

func Lstat(name string) (fi FileInfo, err error)

> Lstat returns a FileInfo describing the named file. If the file is a symbolic link, the returned FileInfo describes the symbolic link. Lstat makes no attempt to follow the link. If there is an error, it will be of type *PathError.

EDIT:

Then returned os.FileInfo will only allow you to check if 'name' is a link or not (fi.Mode() & os.ModeSymlink != 0). If it is, then use os.Readlink to get the pointee:

func Readlink(name string) (string, error)

>Readlink returns the destination of the named symbolic link. If there is an error, it will be of type *PathError.

答案3

得分: 0

我遇到了一个问题,filepath.EvalSymlinks() 在 Mac 上将解析的链接前缀添加了 /private/,而这些链接实际上位于 /tmp/ 目录下(可能符号链接不应该指向那里)。

另一方面,os.Readlink() 在 Mac 上返回的是绝对路径,而在 Ubuntu 上返回的是相对路径。

因此,为了确保获取绝对路径,以下解决方案对我有效:

resolvedLink, _ := os.Readlink(someSymlink) // TODO: 在这里处理错误
if !filepath.IsAbs(resolvedLink) { // os.Readlink 的输出与操作系统有关...
    resolvedLink = path.Join(path.Dir(someSymlink), resolvedLink)
}
英文:

I had the problem that filepath.EvalSymlinks() prepended /private/ to resolved links that were in /tmp/ on Mac (maybe symlinks are not supposed to be pointing there).

os.Readlink() on the other hand, returned an absolute path on Mac, but a relative path on Ubuntu.

Therefore, to be sure to retrieve an absolute path, the following solution worked for me:

resolvedLink, _ := os.Readlink(someSymlink) // TODO: Handle error here
if !filepath.IsAbs(resolvedLink) { // Output of os.Readlink is OS-dependent...
    resolvedLink = path.Join(path.Dir(someSymlink), resolvedLink)
}

huangapple
  • 本文由 发表于 2013年8月5日 23:33:01
  • 转载请务必保留本文链接:https://go.coder-hub.com/18062026.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定