Go之获取Windows下文件是否隐藏

起初,做了个小程序,用来检测磁盘中所有的文件


package main
import(
  "fmt"
  "io/ioutil"
  "os"
)
var dirpath ="D:\\"
func main(){
  CheckDir(dirpath)
}
func CheckDir(dirpath string){
  dirs, err := ioutil.ReadDir(dirpath)
  if err !=nil{
    panic("目录输入有误!")
  }
  for _, dir := range dirs {
    if dir.IsDir(){
    if dir.Name()=="System Volume Information"{
      fmt.Println("检测目录:", dirpath+"\\"+dir.Name(),"sys", dir.Sys())
      return
    }
    fmt.Println("检测目录:", dirpath+"\\"+dir.Name(),"sys", dir.Sys())
      CheckDir(dirpath +"\\"+ dir.Name())
    }else{
        fmt.Println("文件:", dirpath+"\\"+dir.Name(),"大小:", dir.Size())
        if dir.Size()==0{
        fmt.Println("删除文件:", dirpath+"\\"+dir.Name(), dir.Size())
       }
    }
  }
}

输出结果为:

文件: D:\\My Documents\Downloads\wcftestclient_exe.rar 大小: 110608

检测目录: D:\\SoftDown sys &{16 {2081520578 30419524} {1134116594 30422735} {1134116594 30422735} 0 0}

文件: D:\\SoftDown\Sublime Text Build 3012 Setup.exe 大小: 7051120

检测目录: D:\\SoftDown\Vice.2015.720p.WEB-DL.DD5.1.H.264-PLAYNOW sys &{16 {753370423 30421925} {753410426 30421925} {753420426 30421925} 0 0}

文件: D:\\SoftDown\Vice.2015.720p.WEB-DL.DD5.1.H.264-PLAYNOW\Vice.2015.720p.WEB-DL.DD5.1.H.264-PLAYNOW.mkv.tdl 大小: 3255167129

文件: D:\\SoftDown\Vice.2015.720p.WEB-DL.DD5.1.H.264-PLAYNOW\f7a8aa8e2082c4ebe28f2c26cf16e4b08a27d5c1.torrent 大小: 31751

文件: D:\\SoftDown\Vice.2015.720p.WEB-DL.DD5.1.H.264-PLAYNOW.qud.cfg 大小: 556

文件: D:\\SoftDown\[iPlaySoft.com]VS2013_RTM_ULT_CHS.iso 大小: 3077509120

检测目录: D:\\System Volume Information sys &{22 {1206047926 30310737} {1206983927 30310737} {1206983927 30310737} 0 0}

panic: 目录输入有误!

goroutine 1 [running]:
main.CheckDir(0xc0820585c0, 0x1d)
F:/goproj/GitTest.git/trunk/src/WebSite/main.go:22 +0xde main.CheckDir(0x4f3890, 0x3)
F:/goproj/GitTest.git/trunk/src/WebSite/main.go:28 +0x46a main.main()
F:/goproj/GitTest.git/trunk/src/WebSite/main.go:15 +0xfc

这里会报一个异常

D:\System Volume Information Microsoft的解答
本文介绍如何访问 System Volume Information 文件夹。System Volume Information 文件夹是一个隐藏的系统文件夹,系统还原工具使用此文件夹来存储它的信息和还原点。计算机的每个分区上都有一个 System Volume Information 文件夹。为了进行故障排除,可能需要访问此文件夹。

于是就要判断文件是否是隐藏文件,但是Golang api中并未直接给出这个IsHidden属性

调式源码得知:

os.Stat方法可以获取到一个FileInfo,于是写了如下代码   fileinfo, _ := os.Stat(dirpath) sysifno := fileinfo.Sys() fmt.Println(sysifno)

  1. os.Stat
  2. os包中的func Lstat(name string) (fi FileInfo, err error)
  3. 通过 fs,err:=&fileStat{name: basename(name)} 这个初始化得到了一个FileInfo对象。

代码:

type fileStat struct {
name string
sys syscall.Win32FileAttributeData
// used to implement SameFile
sync.Mutex
path string
vol uint32
idxhi uint32
idxlo uint32
}
type Win32FileAttributeData struct {
FileAttributes uint32
CreationTimeFiletime
LastAccessTimeFiletime
LastWriteTimeFiletime
FileSizeHigh uint32
FileSizeLow uint32
}

然后调用 syscall.GetFileAttributesEx(namep, syscall.GetFileExInfoStandard, (*byte)(unsafe.Pointer(&fs.sys))) 将第3步中的fs传入次方法中,调用kernel32.dll的GetFileAttributes方法获取了文件属性

kernel32.dll的GetFileAttributes方法返回值如下:

在MSDN中,文件总共有15种属性,根据磁盘的分区格式不同,文件的属性也会不同。

现在针对GetFileAttributes函数的返回值做以下整理

返回字段 返回值 属性类型
FILE_ATTRIBUTE_READONLY 1 只读
FILE_ATTRIBUTE_HIDDEN 2 隐藏
FILE_ATTRIBUTE_SYSTEM 4 系统
FILE_ATTRIBUTE_DIRECTORY 16 目录
FILE_ATTRIBUTE_ARCHIVE 32 存档
FILE_ATTRIBUTE_DEVICE 64 保留
FILE_ATTRIBUTE_NORMAL 128 正常
FILE_ATTRIBUTE_TEMPORARY 256 临时
FILE_ATTRIBUTE_SPARSE_FILE 512 稀疏文件
FILE_ATTRIBUTE_REPARSE_POINT 1024 超链接或快捷方式
FILE_ATTRIBUTE_COMPRESSED 2048 压缩
FILE_ATTRIBUTE_OFFLINE 4096 脱机
FILE_ATTRIBUTE_NOT_CONTENT_INDEXED 8192 索引
FILE_ATTRIBUTE_ENCRYPTED 16384 加密
FILE_ATTRIBUTE_VIRTUAL 65536 虚拟

橙色标记的属性为Windows系统中文件的公有属性,其中“只读”、“隐藏”、“系统”、“存档”为文件的四种基本属性。compressed,content_indexed,encrypted只存在于NTFS分区中。

文件去掉全部属性后(四种基本属性),将自动标记为normal。同时具有system和hidden属性的文件会在系统中彻底隐形,这也是病毒常用的伎俩。 commpressed和encrypted不能共存。默认情况下文件都有content_indexed属性

这里就能够理解这里输出的
FileAttributes = 22
检测目录:D:\System Volume Information sys &{22 {1206047926 30310737} {1206983927 30310737} {1206983927 30310737} 0 0}

22代表的是也就是
1 0 0 0 0 16 目录
1 0 0 4 系统
& 1 0 2 隐藏
-—————-
1 0 1 1 0 = 22

代表此文件是隐藏文件

检测目录: D:\SoftDown\Vice.2015.720p.WEB-DL.DD5.1.H.264-PLAYNOW sys &{16 {753370423 30421925} {753410426 30421925} {753420426 30421925} 0 0}
16 目录
这样就很明确了:也就是说如果二进制中倒数第二位为1,代表是隐藏目录(文件)

如此就能进行判断了


package main
import(
    "fmt"
    "io/ioutil"
    "os"
    "reflect"
    "strconv"
)
var dirpath ="D:\\"
func main(){
    CheckDir(dirpath)
}
func CheckDir(dirpath string){
  dirs, err := ioutil.ReadDir(dirpath)
  if err !=nil{
      panic("目录输入有误!")
  }
  for _, dir := range dirs {
    if dir.IsDir(){
      if!CheckIsHidden(dir){
        fmt.Println("检测目录:", dirpath+"\\"+dir.Name())
        CheckDir(dirpath +"\\"+ dir.Name())
      }
    }else{
      fmt.Println("文件:", dirpath+"\\"+dir.Name(),"大小:", dir.Size())
      if dir.Size()==0{
        fmt.Println("删除文件:", dirpath+"\\"+dir.Name(), dir.Size())
      }
    }
  }
}
func CheckIsHidden(file os.FileInfo)bool{
//"通过反射来获取Win32FileAttributeData的FileAttributes
    fa := reflect.ValueOf(file.Sys()).Elem().FieldByName("FileAttributes").Uint()
    bytefa :=[]byte(strconv.FormatUint(fa,2))
    if bytefa[len(bytefa)-2]=='1'{
      fmt.Println("隐藏目录:", file.Name())
      return true
    }
    return false
}

本文来自:博客园

感谢作者:anbylau2130

查看原文:Go之获取Windows下文件是否隐藏

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。