无法使用go中的filepath.Walk()重命名给定路径中的所有目录

时间:2018-01-11 11:47:58

标签: go

这是我的访问功能,

func visit(path string, f os.FileInfo, err error) error {
    if !f.IsDir() {
        return nil
    }
    str := path
    if str == config.Path {
        return nil
    }
    if str == config.LatestPath {
        return nil
    }
    dir := str
    dir = strings.TrimPrefix(str, filepath.Dir("C:\\Users\\Mark\\Desktop\\testfolder\\"))
    slashes := strings.Count(dir, "\\")
    if slashes < config.PrevSlashes {
        x := len(config.Slashes) - 1
        for x > slashes {
            config.Slashes[x] = 0
            x--
        }
    }
    config.Slashes[slashes]++
    config.PrevSlashes = slashes
    prename := ""
    for k, v := range config.Slashes {
        if k != 0 {
            if k <= slashes {
                prename += strconv.Itoa(v) + "."
            }
        }
    }
    fmt.Println(config.Slashes)
    myRegex := `(\\(?P<number>[\d\.]*))  \w`
    for i := 0; i < slashes-1; i++ {
        myRegex += `(\\(?P<number` + strconv.Itoa(i) + `>[\d\.]*))  \w*`
    }
    re := regexp.MustCompile(myRegex)
    for i, match := range re.FindAllString(dir, -1) {
        return nil
        fmt.Println(i, match)
    }
    Cdir := filepath.Dir(path)
    newpath := fmt.Sprintf("%s\\%s  %s", Cdir, prename, f.Name())
    config.LatestPath = path
    os.Rename(path, newpath)
    return nil
}

文件夹结构如下所示

testfolder\a\aa\aaa, 
testfolder\a\aa\aab, 
testfolder\a\aa\aac, 
testfolder\a\ab\aaa

我遇到的问题是filepath,Walk()没有看到更改的目录名称。

首先将testfolder \ a \ aa \ aaa重命名为testfolder \ 1。 a \ aa \ aaa然后它尝试将testfolder \ a \ aa \ aaa重命名为testfolder \ a \ 1。 aa \ aaa但我希望它重命名testfolder \ 1。 a \ aa \ aaa to testfolder \ 1。一\ 1.1。 AA \ AAA

最终结果应该是

\testfolder\1. a\1.1. aa\1.1.1. aaa
\testfolder\1. a\1.1. aa\1.1.2. aab
\testfolder\1. a\1.1. aa\1.1.3. aac
\testfolder\1. a\1.2. ab\1.2.1. aaa
\testfolder\1. a\1.2. ab\1.2.2. aab
\testfolder\2. b\2.1. aa\2.1.1. aaa
\testfolder\2. b\2.1. aa\2.2.2. aab

简单地说我想命名一个目录“x.name”及其中的文件夹“x.x. name”,其中x是一个数字

编辑1 :我通过计算路径名并将它们放入数组然后在filepath.Walk()函数完成后重命名目录来解决这个问题

func visit(path string, f os.FileInfo, err error) (error) {
if err != nil {
    log.Fatal(err)
}
if !f.IsDir() {
    return nil
}
str := path
if str == config.Path {
    return nil
}
dir := str
dir = strings.TrimPrefix(str, filepath.Dir("C:\\Users\\Mark\\Desktop\\testfolder\\"))
slashes := strings.Count(dir, "\\")
if slashes < config.PrevSlashes {
    x := len(config.Slashes) - 1
    for x > slashes {
        config.Slashes[x] = 0
        x--
    }
}
config.Slashes[slashes]++
config.PrevSlashes = slashes
prename := ""
for k, v := range config.Slashes {
    if k != 0 {
        if k <= slashes {
            prename += strconv.Itoa(v) + "."
        }
    }
}
myRegex := `(\\(?P<number>[\d\.]*))  \w`
for i := 0; i < slashes-1; i++ {
    myRegex += `(\\(?P<number` + strconv.Itoa(i) + `>[\d\.]*))  \w*`
}
re := regexp.MustCompile(myRegex)
for i, match := range re.FindAllString(dir, -1) {
    config.Dirpaths[slashes] = fmt.Sprintf("%s", f.Name())
    return nil
    fmt.Println(i, match)
}
config.Dirpaths[slashes] = fmt.Sprintf("%s  %s", prename, f.Name())
prenameOld := ""
for k, v := range config.Dirpaths {
    if k != 0 {
        if v != "" {
            if k == slashes {
                break
            }
            prenameOld += v + "\\"
        }
    }
}
oldname := strings.TrimRight(config.Path+prenameOld+f.Name(), "\\")
newName := strings.TrimRight(config.Path+prenameOld+config.Dirpaths[slashes], "\\")
if len(config.OldNames) != config.MaxDir {
    config.OldNames = append(config.OldNames, oldname)
    config.NewNames = append(config.NewNames, newName)
}
return nil
}

1 个答案:

答案 0 :(得分:3)

如果您查看filepath.Walk的{​​{3}},您会看到它执行以下操作:

  • 获取排序列出的当前目录的名称
  • 代表每个名字:
    • 调用您的回调函数
    • 致电walk(name)

使用您指定的目录,testfolder内的第一个电话将用于testfolder/a,因为testfolder/1尚不存在。

无论您做什么,Walk都不会重新读取testfolder/,因此永远不会看到新的1. a子目录。

Walk期间重命名目录/文件是获取错误行为的好方法。 相反,我建议你自己列出目录中的文件并进行自己的递归。

有些事情:

  • 选择下一个dir进行处理(默认情况下为testfolder
  • 使用source
  • 读取dir的当前子目录/文件 每个条目
    • 根据需要重命名
    • 将新名称添加到要处理的目录列表

这使用迭代。或者,您可以递归新名称(这是filepath.Walk失败的地方,因为它不知道新名称。)