意图:
Go 是否具有在 Linux 上执行类似于命令 file -s <path>
的特殊 文件统计的功能(包或其他)
示例:
[root@localhost ~]# file /proc/uptime
/proc/uptime: empty
[root@localhost ~]# file -s /proc/uptime
/proc/uptime: ASCII text
用例:
我在/proc/* 中有一个 fileglob 文件,我需要非常快速地检测它们是否真的是空的而不是看起来是空的。
使用 os 包:
代码:
result,_ := os.Stat("/proc/uptime")
fmt.Println("Name:",result.Name()," Size:",result.Size()," Mode:",int(result.Mode()))
fmt.Printf("%q",result)
结果:
Name: uptime Size: 0 Mode: 292
&{"uptime" '\x00' 'Ĥ' {%!q(int64=63606896088) %!q(int32=413685520) %!q(*time.Location=&{ [] [] 0 0 <nil>})} {'\x03' %!q(uint64=4026532071) '\x01' '脤' '\x00' '\x00' '\x00' '\x00' '\x00' 'Ѐ' '\x00' {%!q(int64=1471299288) %!q(int64=413685520)} {%!q(int64=1471299288) %!q(int64=413685520)} {%!q(int64=1471299288) %!q(int64=413685520)} ['\x00' '\x00' '\x00']}}
明显的解决方法:
有以下明显的解决方法。但是需要调用 bash shell 来获取文件统计信息有点过头了。
output,_ := exec.Command("bash","-c","file -s","/proc/uptime").Output()
//parse output etc...
编辑/我的实际用例:
快速确定哪些文件大小为零,而无需先读取每个文件。
file -s /cgroup/memory/lsf/<cluster>/*/tasks | <clean up commands> | uniq -c
6 /cgroup/memory/lsf/<cluster>/<jobid>/tasks: ASCII text
805 /cgroup/memory/lsf/<cluster>/<jobid>/tasks: empty
所以在这种情况下,我知道只有这 6 个作业正在运行,其余 (805) 个作业已终止。读取文件的工作方式如下:
# cat /cgroup/memory/lsf/<cluster>/<jobid>/tasks
#
或
# cat /cgroup/memory/lsf/<cluster>/<jobid>/tasks
12352
53455
...
最佳答案
恐怕您在这里可能会感到困惑:file
的特殊之处在于它“知道”一组启发式方法来执行其任务。
据我所知,Go 在其标准库中没有类似的东西,而且我还没有遇到过实现类似 file
功能的第 3 方包(尽管我邀请您在 http://godoc.org 上按相关关键字搜索 )
另一方面,Go 提供了对底层操作系统的系统调用接口(interface)的完全访问,所以当涉及到以 file
的方式查询操作系统时,没有什么是你不能做的去吧。
所以我建议你只获取 file
的源代码,了解它在“-s”命令行选项打开的模式下做了什么,并在你的 Go 代码中实现它。
如果您有任何问题,我们会尽力让您解决具体问题。
更新
看起来我已经设法掌握了 OP 正在努力解决的问题:一个简单的检查:
$ stat -c %s /proc/$$/status && wc -c < $_
0
849
也就是说,对 /proc
下的文件的 stat
调用显示它没有内容,但实际上从该文件读取会返回该内容。
好的,所以解决方案很简单:与其在遍历文件系统的子树时调用 os.Stat()
,不如尝试从文件中读取单个字节,比如:
var buf [1]byte
f, err := os.Open(fname)
if err != nil {
// do something, or maybe ignore.
// A not existing file is OK to ignore
// (the POSIX error code will be ENOENT)
// because after the `path/filepath.Walk()` fetched an entry for
// this file from its directory, the file might well have gone.
}
_, err = f.Read(buf[:])
if err != nil {
if err == io.EOF {
// OK, we failed to read 1 byte, so the file is empty.
}
// Otherwise, deal with the error
}
f.Close()
你可能会尝试更聪明,首先获取统计信息
(使用对 os.Stat()
的调用)来查看文件是否为常规文件—
不要尝试从套接字等读取数据。
关于linux - 如何在 Linux 上用纯 Go 实现 "file -s <file>"?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38963896/