更改文件名路径目录

时间:2018-05-15 19:27:30

标签: go filepath

我需要更改相对于给定文件夹的文件名路径 我正在处理多用户共享存储桶,用户不知道完整的文件路径会很好。

我有一个例子,但看起来有点脏。

package main

import (
    "fmt"
    "strings"
)

func main() {
    secretUrl := "allusers/user/home/path/to/file"
    separator := "home/"

    newUrl := strings.Split(secretUrl, separator)

    newUserUrl := separator + newUrl[len(newUrl)-1]
    fmt.Printf("%q\n", newUserUrl)

}

此外,新路径需要从分离点开始。

还有另一种更优雅的方式吗?我们将不胜感激。

2 个答案:

答案 0 :(得分:2)

我认为一个很好的独立于平台的解决方案是使用golang路径/文件路径Split功能。不假设分隔符的路径是什么,处理卷等等......

subpath("home", "allusers/user/home/path/to/file")

使用

进行通话
func subpath(homeDir, prevDir string) (subFiles string, found bool) {
    for {
        dir, file := filepath.Split(prevDir)
        if len(subFiles) > 0 {
            subFiles = file + string(filepath.Separator) + subFiles
        } else {
            subFiles = file
        }
        if len(dir) == 0 || dir == prevDir {
            return
        }
        prevDir = dir[:len(dir) - 1]
        if file == homeDir {
            found = true
            // look for it lower down
            lower, foundAgain := subpath(homeDir, prevDir)
            if foundAgain {
                subFiles = lower + string(filepath.Separator) + subFiles
            }
            return
        }
    }
}

处理" home"可能不止一次出现,你希望匹配第一个:

path, found = subpath("home", "allusers/user/home/path/home2/home/to/file")
if found {
    fmt.Printf("%q\n", path)
} else {
    fmt.Printf("not found\n")
}

使用

进行通话
import os
import mutagen
import mutagen.id3
from mutagen.id3 import ID3
from mutagen.mp3 import MP3
from mutagen.easyid3 import EasyID3

files = os.listdir(r'C:\Users\Kurt\Music\Music\Brad Paisley\python test')
count = 0

for file in files:
    path = file
    try:
        tag = EasyID3(path)
    except:
        tag = mutagen.File(path, easy=True)
        tag.add_tags()
    tag['tracknumber'] = count + 1
    tag.save(v2_version=3)
    file.save()
    count = count + 1

答案 1 :(得分:1)

经验法则 不要将文件路径作为字符串 进行操作。边缘情况太多了。 Go有pathfilepath个库来操纵路径。

但也有例外。 Go的pathfilepath库的功能有限,例如它缺少将路径拆分为数组或检查一个文件路径是否是另一个文件路径的子句的方法。有时使用字符串函数效率更高。您可以先调用filepath.Clean来规范化它们,从而避免许多问题。

如果前缀始终为allusers/user/home,那么您可以在清理路径后将路径拆分为切片,并将它们作为数组进行比较。

// Clean will take care of // and trailing /
secret := filepath.Clean("allusers//user/home//path/to/file")
base   := filepath.Clean("allusers/user/home/")

// Clean has made splitting on / safe.
secret_parts := strings.Split(secret, "/")
base_parts   := strings.Split(base, "/")

现在我们有两个要比较的所有部分的数组。首先,检查以确保base_parts确实是secret_parts的前缀secret_partsbase_parts的前几个元素。与func sliceHasPrefix( s, prefix []string ) bool { if len(s) < len(prefix) { return false } return reflect.DeepEqual(prefix, s[0:len(prefix)]) } 中的数字相同。

if sliceHasPrefix( secret_parts, base_parts ) {
    fmt.Println( filepath.Join(secret_parts[len(base_parts):]...) )
} else {
    panic("secret is not inside base")
}

然后我们可以使用reflect.DeepEqual将剩余部分重新组合在一起。

{x: "one"}