如何在Go中检测文件夹中的隐藏文件 – 跨平台方法

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

How to detect Hidden Files in a folder in Go - cross-platform approach

问题

我正在使用golang中的filePath.Walk方法遍历一个挂载的文件夹,但它也返回隐藏文件。我必须跳过这些隐藏文件。
对于MaxOS和Linux,我们可以通过文件名中的.前缀来检测隐藏文件,但是对于Windows,当我尝试使用syscall提供的GetFileAttributes方法时,它无法检测到这些方法并抛出错误。

使用以下方法获取文件:

err := filepath.Walk(prefix, func(docPath string, f os.FileInfo, err error) error {

以下是我尝试检测隐藏文件的方法:

import (
	"runtime"
	"syscall"
)

func IsHiddenFile(filename string) (bool, error) {
	if runtime.GOOS == "windows" {
		pointer, err := syscall.UTF16PtrFromString(filename)
		if err != nil {
			return false, err
		}
		attributes, err := syscall.GetFileAttributes(pointer)
		if err != nil {
			return false, err
		}
		return attributes&syscall.FILE_ATTRIBUTE_HIDDEN != 0, nil
	} else {
		// unix/linux file or directory that starts with . is hidden
		if filename[0:1] == "." {
			return true, nil
		}
	}
	return false, nil
}

错误信息:

.../ undefined: syscall.UTF16PtrFromString
.../ undefined: syscall.GetFileAttributes
.../ undefined: syscall.FILE_ATTRIBUTE_HIDDEN

我在文件开头添加了// +build windows,在包名之前,如此处建议的:https://stackoverflow.com/questions/27361715/syscall-variables-undefined,但仍然不起作用,并且抛出相同的错误。

我想知道go是否提供了一些常用的方法来检测文件是否隐藏?或者是否有一种方法可以在一开始就获取某个挂载目录中的所有文件/文件夹而不接收隐藏文件?

真的很期待在这里收到一些反馈,谢谢。


编辑:修复了上述问题(请参考下面的评论),我还想知道在连接到远程服务器(SMB)时如何检测隐藏文件,远程系统可以运行任何操作系统,并且我们根据其运行的系统编译这些方法。在这种情况下,我们如何检测隐藏文件?

英文:

I'm iterating through a mounted folder via filePath.Walk method in golang, but it returns the hidden files as well. I have to skip those hidden files.
For MaxOS and Linux, we can detect hidden file via .prefix in the filename, but for windows, when I'm trying to us this method GetFileAttributes, provided by "syscall", it's not detecting these methods and throwing an error.

Using below method to fetch the file

err := filepath.Walk(prefix, func(docPath string, f os.FileInfo, err error) error {

Below is how I'm trying to detect the hidden files

import (
  "runtime"
  "syscall"
)

func IsHiddenFile(filename string) (bool, error) {

if runtime.GOOS == "windows" {
	pointer, err := syscall.UTF16PtrFromString(filename)
	if err != nil {
		return false, err
	}
	attributes, err := syscall.GetFileAttributes(pointer)
	if err != nil {
		return false, err
	}
	return attributes&syscall.FILE_ATTRIBUTE_HIDDEN != 0, nil
} else {
	// unix/linux file or directory that starts with . is hidden
	if filename[0:1] == "." {
		return true, nil
	}
}
return false, nil

}

Error :

.../ undefined: syscall.UTF16PtrFromString
.../ undefined: syscall.GetFileAttributes
.../ undefined: syscall.FILE_ATTRIBUTE_HIDDEN

I added this // +build windows in the start of the file before package name as suggested here : https://stackoverflow.com/questions/27361715/syscall-variables-undefined but it's sill not working and throwing the same error.

I need to know if go provides some common method to detect if a file is hidden or not? Or is there a way I can fetch all the files/folder in some mounted directory without receiving hidden files in the first place?

Really looking forward on receiving some feedback here, thanks.


EDIT : Fixed the above mentioned issue (please refer to the comments below), I also wants to know how can we detect the hidden file when we are connected with the remote server (SMB), the remoter system could be running any OS, and we compile these method based on the system it's running on. How can we detect Hidden files in that scenario ?

答案1

得分: 8

条件编译是正确的方法,但它适用于源文件级别,所以你需要两个单独的文件。

例如:

hidden_notwin.go:

//go:build !windows

package main

func IsHiddenFile(filename string) (bool, error) {
	return filename[0] == '.', nil
}

hidden_windows.go:

//go:build windows

package main

import (
	"syscall"
)

func IsHiddenFile(filename string) (bool, error) {
	pointer, err := syscall.UTF16PtrFromString(filename)
	if err != nil {
		return false, err
	}
	attributes, err := syscall.GetFileAttributes(pointer)
	if err != nil {
		return false, err
	}
	return attributes&syscall.FILE_ATTRIBUTE_HIDDEN != 0, nil
}

请注意,上面的//go:build windows标签是可选的 - _windows源文件后缀已经起到了魔法的作用。有关更多详细信息,请参阅go命令 - 构建约束

英文:

Conditional compilation is the right way to go, but it applies at source file level, so you need two separate files.

For example:

hidden_notwin.go:

//go:build !windows

package main

func IsHiddenFile(filename string) (bool, error) {
	return filename[0] == '.', nil
}

hidden_windows.go:

//go:build windows

package main

import (
	"syscall"
)

func IsHiddenFile(filename string) (bool, error) {
	pointer, err := syscall.UTF16PtrFromString(filename)
	if err != nil {
		return false, err
	}
	attributes, err := syscall.GetFileAttributes(pointer)
	if err != nil {
		return false, err
	}
	return attributes&syscall.FILE_ATTRIBUTE_HIDDEN != 0, nil
}

Note that //go:build windows tag above is optional - the _windows source file suffix does the magic already. For more details see go command - Build constraints.

huangapple
  • 本文由 发表于 2021年12月9日 22:51:31
  • 转载请务必保留本文链接:https://go.coder-hub.com/70291933.html
匿名

发表评论

匿名网友

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

确定