英文:
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("/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("/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)
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论