1.ToSlash(path string) string

将相关平台的路径分隔符转为/

package main

import (
"fmt"
"os"
"path/filepath"
) func main() {
sep := os.PathSeparator // 查看当前平台的系统路径分隔符,windows平台是\
fmt.Println(string(sep)) // \ // 将分割符转为/
fmt.Println(filepath.ToSlash(`C:\python37\python.exe`)) // C:/python37/python.exe // 注意:该函数不在意路径是否存在,只是当成普通的字符串进行处理
// 比如我输入一个不存在的路径也是可以的
fmt.Println(filepath.ToSlash(`C:\python37\python.exe\python.exe`)) // C:/python37/python.exe/python.exe
}

2.FromSlash(path string) string

和ToSlash相反,是将/转化为相关系统的路径分隔符

package main

import (
"fmt"
"path/filepath"
) func main() {
fmt.Println(filepath.FromSlash(`C:/python37/python.exe`)) // C:\python37\python.exe
fmt.Println(filepath.FromSlash(`C:\python37/python.exe`)) // C:\python37\python.exe
fmt.Println(filepath.FromSlash(`C:\python37\python.exe////`)) // C:\python37\python.exe\\\\ /*
可以看到,这两个函数只是简单的字符串替换罢了,在源码里面也是这么做的
func FromSlash(path string) string {
if Separator == '/' {
return path
}
return strings.ReplaceAll(path, "/", string(Separator))
}
另外,这两个函数在linux下面也能用,但是没有意义,因为linux的路径分隔符就是/
*/
}

3.Dir(path string) string

获取path中最后一个分割符前面的部分,类似于python中的os.path.dirname(path)

package main

import (
"fmt"
"path/filepath"
) func main() {
path := `c:\python37\python.exe`
fmt.Println(filepath.Dir(path)) // c:\python37
}

4.Base(path string) string

获取path中最后一个分割符后面的部分,类似于python中的os.path.basename(path)

package main

import (
"fmt"
"path/filepath"
) func main() {
path := `c:\python37\python.exe`
fmt.Println(filepath.Base(path)) // python.exe
}

5.Split(path string) (dir, file string)

相当于是Dir和Base的组合,得到最后一个分割符的前面和后面两部分,类似于python中os.path.split

package main

import (
"fmt"
"path/filepath"
) func main() {
path := `c:\python37\python.exe`
dir, file := filepath.Split(path)
fmt.Println(dir, file) // c:\python37\ python.exe
}

6.Ext(path string) string

获取path中的文件扩展名,类似于python中的os.path.splitext(path)[1]

package main

import (
"fmt"
"path/filepath"
) func main() {
path := `c:\python37\python.exe`
fmt.Println(filepath.Ext(path)) // .exe
}

7.Rel(basepath, targpath string) (string, error)

获取targpath相对于basepath的路径,怎么理解呢?就是basepath进行什么样的操作,才能得到targpath。其中两者必须都是相对路径或者绝对路径

package main

import (
"fmt"
"path/filepath"
) func main() {
path1 := `c:\python37\python.exe`
path2 := `c:\python37`
p1, err1 := filepath.Rel(path1, path2)
if err1 != nil {
fmt.Println(err1)
}else{
fmt.Println(p1) // ..
}
//得到的结果是..,表示path1组合..就能得到path2 path1 = `c:\python37`
path2 = `c:\python37\python.exe`
p2, err2 := filepath.Rel(path1, path2)
if err2 != nil {
fmt.Println(err2)
}else{
fmt.Println(p2) // python.exe
}
// 表示path1再组合python.exe就能得到path2 path1 = `c:\python37`
path2 = `c:\go`
p3, err3 := filepath.Rel(path1, path2)
if err3 != nil {
fmt.Println(err3)
}else{
fmt.Println(p3) // ..\go
} path1 = `c:\python37`
path2 = `d:\overwatch`
p4, err4 := filepath.Rel(path1, path2)
if err4 != nil {
fmt.Println(err4) // Rel: can't make d:\overwatch relative to c:\python37
}else {
fmt.Println(p4)
}
//在window上,如果跨越了盘符,是没有办法的 }

8.Join(elem ...string) string

将多个路径进行组合

package main

import (
"fmt"
"path/filepath"
) func main() {
path1 := `c:\python37`
path2 := `lib`
path3 := `site-packages`
path4 := `tornado`
fmt.Println(filepath.Join(path1, path2, path3, path4)) // c:\python37\lib\site-packages\tornado fmt.Println(filepath.Join(path1, path2, "scripts", "pip")) // c:\python37\lib\scripts\pip
fmt.Println(filepath.Join(path1, path2, "..", "scripts", "pip")) // c:\python37\scripts\pip
// ..相当于上一层目录
}

9.Clean(path string) string

清理路径中的多余字符

package main

import (
"fmt"
"path/filepath"
) func main() {
path := `c:\python\\\python37\..\\\python.ext\\\aaa\.\::::\\xx`
fmt.Println(filepath.Clean(path)) // :\python\python.ext\aaa\::::\xx
// 清除的主要是\\\和\\, 都换成了\,个人觉得不是很常用
}

10.Abs(path string) (string, error)

获取path的绝对路径,类似于python中的os.path.abspath

package main

import (
"fmt"
"path/filepath"
) func main() {
path1 := `.`
abs_path1, err1 := filepath.Abs(path1)
if err1 != nil {
fmt.Println(err1)
}else {
fmt.Println(abs_path1) // D:\komeijisatori
} //如果是点的话,那么默认是当前go文件所在的工作区的目录
}

11.IsAbs(path string) bool

判断当前路径是否是绝对路径

package main

import (
"fmt"
"path/filepath"
) func main() {
path1 := `.`
flag := filepath.IsAbs(path1)
fmt.Println(flag) // false fmt.Println(filepath.IsAbs(`c:\python37\python.exe`)) // true
}

12.VolumeName(path string) string

返回path所在的卷名,比如c:\python37\python.exe就是c:,而linux中/opt/python/bin就是/opt/python

package main

import (
"fmt"
"path/filepath"
) func main() {
path1 := `c:\python37\python.exe`
fmt.Println(filepath.VolumeName(path1)) // c:
}

13.EvalSymlinks(path string) (string, error)

返回当前链接(快捷方式)所指向的文件

14.Match(pattern, name string) (matched bool, err error)

判断 name 是否和指定的模式 pattern 完全匹配,有点类似于python中的fnmatch,但是匹配的方式不太一样

package main

import (
"fmt"
"path/filepath"
) func main() {
/*
?:匹配单个任意字符
*:匹配任意个任意字符
[]:匹配某个范围内的任意一个字符
[^]:匹配某个范围外的任意一个字符
[a-z]:也可以使用类似于正则表达式的模式,使用-表示一个区间
\:用来进行转义,匹配实际的字符,比如\*表示*, \[匹配[,但是?是不需要转义的,因为?表示匹配任意一个字符,所以也包含?
[]里面也可以直接包含[ ? *等特殊字符,无需转义。但是] -这些字符则必须要转义,必须是\]或者\-才能匹配]和-
*/
fmt.Println(filepath.Match(`???`, "abc")) // true <nil>
fmt.Println(filepath.Match(`???`, "???")) // true <nil>
fmt.Println(filepath.Match(`???`, "abcd")) // false <nil> fmt.Println(filepath.Match(`*`, "abc")) // true <nil>
fmt.Println(filepath.Match(`*`, "")) // true <nil> fmt.Println(filepath.Match(`???[?`, "abc[e")) // false syntax error in pattern fmt.Println(filepath.Match(`[aA][bB][cC]`, `aBc`)) // true <nil>
fmt.Println(filepath.Match(`[^aA]*`,`abc`)) // false <nil>
fmt.Println(filepath.Match(`[a-z]*`,`a+b`)) // true <nil> }

15.Glob(pattern string) (matches []string, err error)

列出与指定的模式 pattern 完全匹配的文件或目录(匹配原则同Match)

package main

import (
"fmt"
"io/ioutil"
"path/filepath"
) func main() {
list, err := filepath.Glob(`c:\python37\*`)
if err != nil{
fmt.Println(err)
}else {
for _, v := range list{
fmt.Println(v)
/*
c:\python37\DLLs
c:\python37\Doc
c:\python37\LICENSE.txt
c:\python37\Lib
c:\python37\NEWS.txt
c:\python37\Scripts
c:\python37\Tools
c:\python37\cx_Oracle-doc
c:\python37\etc
c:\python37\include
c:\python37\libs
c:\python37\man
c:\python37\python.exe
c:\python37\python3.dll
c:\python37\python37.dll
c:\python37\pythonw.exe
c:\python37\share
c:\python37\tcl
c:\python37\vcruntime140.dll
*/
}
} //遍历文件还有另一种方式
fileinfo, err := ioutil.ReadDir(`c:\python37`)
if err != nil {
fmt.Println(err)
}else {
// fileinfo则是一个切片,里面的数据类型是os.FileInfo
/*
type FileInfo interface {
Name() string // base name of the file
Size() int64 // length in bytes for regular files; system-dependent for others
Mode() FileMode // file mode bits
ModTime() time.Time // modification time
IsDir() bool // abbreviation for Mode().IsDir()
Sys() interface{} // underlying data source (can return nil)
}
*/
for _, v := range fileinfo{
message := fmt.Sprintf("文件名:%s,大小:%d,是否是目录,%t", v.Name(), v.Size(), v.IsDir())
fmt.Println(message)
/*
文件名:DLLs,大小:0,是否是目录,true
文件名:Doc,大小:0,是否是目录,true
文件名:LICENSE.txt,大小:30195,是否是目录,false
文件名:Lib,大小:0,是否是目录,true
文件名:NEWS.txt,大小:665470,是否是目录,false
文件名:Scripts,大小:0,是否是目录,true
文件名:Tools,大小:0,是否是目录,true
文件名:cx_Oracle-doc,大小:0,是否是目录,true
文件名:etc,大小:0,是否是目录,true
文件名:include,大小:0,是否是目录,true
文件名:libs,大小:0,是否是目录,true
文件名:man,大小:0,是否是目录,true
文件名:python.exe,大小:99856,是否是目录,false
文件名:python3.dll,大小:58896,是否是目录,false
文件名:python37.dll,大小:3748368,是否是目录,false
文件名:pythonw.exe,大小:98320,是否是目录,false
文件名:share,大小:0,是否是目录,true
文件名:tcl,大小:0,是否是目录,true
文件名:vcruntime140.dll,大小:89752,是否是目录,false
*/
}
}
}

16.Walk(root string, walkFn WalkFunc) error

遍历指定目录下的所有子目录,对遍历的项目使用walkFn进行处理,WalkFunc类型如下。

type WalkFunc func(path string, info os.FileInfo, err error) error

这是最后一个例子,我们多写几个例子 

package main

import (
"fmt"
"os"
"path/filepath"
"strings"
) func main() {
walkFn := func(path string, info os.FileInfo, err error) error {
//遍历的时候,会自动将path:文件路径、info:文件信息、err:错误传递进来,我们可以写上自己的逻辑
//获取文件名
filename := info.Name()
if strings.HasSuffix(filename, "__init__.py"){
//如果文件是以__init__.py结尾的话, 直接打印对应的path
fmt.Println(path)
}
//这里我们直接返回nil即可
return nil
} //那么开始遍历,会对遍历的每一个内容都交给walkFn进行处理
err := filepath.Walk(`c:\python37\lib\site-packages\numpy`, walkFn)
if err != nil {
fmt.Println("err =", err)
}
/*
输出结果
c:\python37\lib\site-packages\numpy\__init__.py
c:\python37\lib\site-packages\numpy\compat\__init__.py
c:\python37\lib\site-packages\numpy\compat\tests\__init__.py
c:\python37\lib\site-packages\numpy\core\__init__.py
c:\python37\lib\site-packages\numpy\core\tests\__init__.py
c:\python37\lib\site-packages\numpy\distutils\__init__.py
c:\python37\lib\site-packages\numpy\distutils\command\__init__.py
c:\python37\lib\site-packages\numpy\distutils\fcompiler\__init__.py
c:\python37\lib\site-packages\numpy\distutils\tests\__init__.py
c:\python37\lib\site-packages\numpy\doc\__init__.py
c:\python37\lib\site-packages\numpy\f2py\__init__.py
c:\python37\lib\site-packages\numpy\f2py\tests\__init__.py
c:\python37\lib\site-packages\numpy\fft\__init__.py
c:\python37\lib\site-packages\numpy\fft\tests\__init__.py
c:\python37\lib\site-packages\numpy\lib\__init__.py
c:\python37\lib\site-packages\numpy\lib\tests\__init__.py
c:\python37\lib\site-packages\numpy\linalg\__init__.py
c:\python37\lib\site-packages\numpy\linalg\tests\__init__.py
c:\python37\lib\site-packages\numpy\ma\__init__.py
c:\python37\lib\site-packages\numpy\ma\tests\__init__.py
c:\python37\lib\site-packages\numpy\matrixlib\__init__.py
c:\python37\lib\site-packages\numpy\matrixlib\tests\__init__.py
c:\python37\lib\site-packages\numpy\polynomial\__init__.py
c:\python37\lib\site-packages\numpy\polynomial\tests\__init__.py
c:\python37\lib\site-packages\numpy\random\__init__.py
c:\python37\lib\site-packages\numpy\random\tests\__init__.py
c:\python37\lib\site-packages\numpy\testing\__init__.py
c:\python37\lib\site-packages\numpy\testing\_private\__init__.py
c:\python37\lib\site-packages\numpy\testing\tests\__init__.py
c:\python37\lib\site-packages\numpy\tests\__init__.py
*/
}

统计一下文件个数,分为两个版本,golang版和python版

  • golang

    package main
    
    import (
    "fmt"
    "os"
    "path/filepath"
    "strings"
    "time"
    ) func main() {
    start_time := time.Now().UnixNano()
    //下面我们来统计一下,c:\python37下面有多少个__init__.py文件,有多少个py文件,有多少个不是py文件的文件,有多少个目录
    init_py_file := 0
    py_file := 0
    not_py_file := 0
    dir := 0 walkFn := func(path string, info os.FileInfo, err error) error {
    filename := info.Name()
    is_dir := info.IsDir()
    if strings.HasSuffix(filename, "__init__.py") {
    //如果文件是以__init__.py结尾的话, 别忘了py_file也要++
    init_py_file++
    py_file++
    } else if strings.HasSuffix(filename, ".py") {
    //以.py结尾的话
    py_file++
    } else if is_dir {
    //如果是目录的话
    dir++
    } else {
    //既不是py结尾,也不是目录的话
    not_py_file++
    }
    //这里我们直接返回nil即可
    return nil
    } //那么开始遍历,会对遍历的每一个内容都交给walkFn进行处理
    err := filepath.Walk(`c:\python37`, walkFn)
    if err != nil {
    fmt.Println("err =", err)
    }
    //打印相应的个数
    fmt.Println(fmt.Sprintf("__init__.py文件个数:%d,py文件个数:%d,不是py文件的文件个数:%d,目录个数:%d", init_py_file, py_file, not_py_file, dir))
    /*
    __init__.py文件个数:1965,py文件个数:11911,不是py文件的文件个数:23050,目录个数:7685
    */
    end_time := time.Now().UnixNano()
    fmt.Println("总用时:", (end_time - start_time) / 1e9) // 总用时: 4
    }
  • python

    from pathlib import Path
    import os
    import time start_time = time.perf_counter()
    init_py_file = 0
    py_file = 0
    not_py_file = 0
    dir = 0
    p = Path(r"c:\python37")
    for file in p.rglob("*"):
    if str(file).endswith("__init__.py"):
    init_py_file += 1
    py_file += 1
    elif str(file).endswith(".py"):
    py_file += 1
    elif os.path.isdir(str(file)):
    dir += 1
    else:
    not_py_file += 1 end_time = time.perf_counter()
    print(f"__init__.py文件个数:{init_py_file},py文件个数:{py_file},不是py文件的文件个数:{not_py_file},目录个数:{dir}")
    # __init__.py文件个数:1965,py文件个数:11911,不是py文件的文件个数:23050,目录个数:7684
    print(f"总用时:{end_time - start_time}")
    # 总用时:3.695507357
  • 总结:两者之间效率基本上是一样的,代码量的话,由于golang的{}多占了一行,并且如果不考虑if err != nil之类的话,代码量也基本差不多。但是我们比较一下结果的话,其他的是一样的,只有目录的个数不一样,golang的结果貌似比python多了一个,这是因为,我们递归遍历的是c:\python37,在golang中,把c:\python37这个目录本身也给算进去了,而python没有。所以其他的结果是一致的,但是目录个数的话,golang算出来会比python多一个。当然仔细观察结果的话,稍加思考就能发现原因,这里程序就不再演示了,可以找一个文件或目录数量比较少的打印一下,会发现python没有把最外层的目录打印出来,打印都是指定目录里面的内容。

package main

import (
"fmt"
"os"
"path/filepath"
) func main() {
walkFn := func(path string, info os.FileInfo, err error) error {
is_dir := info.IsDir()
if is_dir{
//如果是目录,那么我们就跳过,不做处理
fmt.Println(fmt.Sprintf("%s是目录,已经跳过", path))
return filepath.SkipDir
}
return nil
}
//那么开始遍历,会对遍历的每一个内容都交给walkFn进行处理
err := filepath.Walk(`c:\python37`, walkFn)
if err != nil {
fmt.Println("err =", err)
}
/*
c:\python37是目录,已经跳过
*/
//可以发现,上来就跳过了,跳过是指整个目录跳过,目录里面有什么也不再关心了
//也可以得出,golang是会处理指定的目录,而python不会,python只处理指定目录里面的内容
}
package main

import (
"fmt"
"os"
"path/filepath"
) func main() {
walkFn := func(path string, info os.FileInfo, err error) error {
filename := info.Name()
is_dir := info.IsDir()
if is_dir && filename == "scripts"{
//如果是目录,并且目录名为scripts,那么我们就跳过,不做处理
fmt.Println(fmt.Sprintf("%s是目录,已经跳过", path))
return filepath.SkipDir
}
return nil
}
//那么开始遍历,会对遍历的每一个内容都交给walkFn进行处理
err := filepath.Walk(`c:\python37`, walkFn)
if err != nil {
fmt.Println("err =", err)
}
/*
c:\python37\Lib\venv\scripts是目录,已经跳过
c:\python37\Tools\scripts是目录,已经跳过
*/
}

filepath:处理文件路径的一把好手的更多相关文章

  1. C#文件路径乱码

    最近学C#,用C#写serialport遇到了一点小问题记录一下. 问题一: if (!string.IsNullOrEmpty(filePath.ToString())) { try { fs = ...

  2. chrome文件上传 /获取文件路径c:/fakepath的解决办法

    jsp页面 <td style="text-align: left;padding-left: 20px;"> <img name="image&quo ...

  3. 文件指针/句柄(FILE*)、文件描述符(fd)以及 文件路径(filepath)的相互转换(转)

    转自: http://blog.csdn.net/jenghau/article/details/5532265 文件指针/句柄(FILE*).文件描述符(fd)以及 文件路径(filepath)的相 ...

  4. Go path/filepath文件路径操作

    本文:https://books.studygolang.com/The-Golang-Standard-Library-by-Example/chapter06/06.2.html path:htt ...

  5. Excel公式 提取文件路径后缀

    我们在代码中获取一个文件路径的后缀,是一个很简单的事. 如C#中,可以通过new FileInfo(filePath).Extension,或者Path.GetExtension(filePath)获 ...

  6. Ruby操作VBA的注意事项和技巧(1):乱码、获取VBA活动和非活动窗口的名称与路径、文件路径的智能拼接与截取(写入日期)

    1.VBA编辑器复制粘贴出来的代码乱码     解决方法:切换到中文输入模式再复制出来就行了 2.获取VBA活动和非活动窗口的名称与路径 Dim wbpath, filename As String ...

  7. iOS获取文件路径

    p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px "PingFang SC"; color: #008400 } p.p2 ...

  8. oc 根据文件路径获取文件大小

    第一种封装: -(NSInteger)getSizeOfFilePath:(NSString *)filePath{ /** 定义记录大小 */ NSInteger totalSize = ; /** ...

  9. .35-浅析webpack源码之babel-loader入口文件路径读取

    在处理./input.js入口文件时,在类型判断被分为普通文件,所以走的文件事件流,最后拼接得到文件的绝对路径. 但是对应"babel-loader"这个字符串,在如下正则中被判定 ...

随机推荐

  1. httpClient模仿Basic Auth

    httpclient代码调用如下: @GetMapping("loginTest") public String httpClientWithBasicAuth() { Strin ...

  2. SQL中group by使用

    多条重复记录,有一个字段可以进行区分,从重复的记录中取出其中一条,可利用group by字段 举例如下: 查询所有 查询地区中的最高分

  3. padding的计算方法

    转自https://blog.csdn.net/qq_34599526/article/details/83755275 VALID:如果卷积核超出特征层,就不再就计算,即卷积核右边界不超出Featu ...

  4. react中key的使用

    面试题: 1). react/vue中的key的作用/内部原理 2). 为什么列表的key尽量不要用index 虚拟DOM的key的作用? 1). 简单的说: key是虚拟DOM对象的标识, 在更新显 ...

  5. Office之什么是高内聚低耦合

    ---恢复内容开始--- 高内聚低耦合,是软件工程中的概念,是判断设计好坏的标准,主要是面向对象的设计,主要是看类的内聚性是否高,耦合度是否低. 粗劣的说就指的是:单独模块间有着强大的凝聚力,不同的模 ...

  6. 2019年icpc区域赛银川站总结

    目录 一.前言 二.10月19日热身赛 三.10月20日正式赛 四.结果 一.前言 比赛前我们队有ccpc厦门和icpc银川的名额,然而这两个地区的时间正好撞了,考虑到银川更容易拿奖,加上我们ACM协 ...

  7. NoSQL--leveldb

    什么是leveldb: leveldb它是一个 NOSQL 存储引擎,它和 Redis 不是一个概念.Redis 是一个完备的数据库,而 LevelDB 它只是一个引擎. LevelDB 还可以将它看 ...

  8. 【go进阶】一个简单的go服务器实现

    光阴似箭,日月如梭,在昨天我终于拿到了自己忙活了半个月的工资. 据说在7月25日有一颗小行星掠过地球,如果真的撞上来,估计31号我就不是乐呵呵的了,应该是直接没了. 如下的代码运行起来就是一个微型go ...

  9. Installation failed with message Failed to commit install session 634765663 with command cmd package

    用小米真机测试时,安装app总会提示这个错误两遍,然后再重新安装. 解决办法:去掉这个√.

  10. mysql 速度优化

    1.添加索引 ALTER TABLE `cw_base_house` ADD INDEX idx_house ( `villageCode`, `buildingNo`, `unitNo`, `hou ...