【问题标题】:An invalid path was specified when tried to rename file尝试重命名文件时指定了无效路径
【发布时间】:2020-02-15 04:44:19
【问题描述】:

我正在 Python 中编写版本升级脚本(自动版本号递增脚本),但我感觉在 Maya 中重命名代码时发生了奇怪的事情。

我不确定 Maya 是如何存储文件路径的,但每当我尝试重命名它时,它都会告诉我“指定了无效路径”。以及我的文件路径。

为了让事情变得更奇怪,我猜它只在几个情况下说这个错误。一旦我尝试从 Maya 的资产文件夹重命名文件(是的,我已经为 Maya 设置了要查找的项目),它给了我这个错误。但是当我从 Maya 的场景文件夹中打开文件时,一切正常。然后,在另一个项目文件夹中,无论我打开资产文件还是场景文件,一切都运行良好。

有人知道发生了什么吗?非常感谢!!!

a = cmds.file (query = True, expandName = True)  #result: D:/DATA/MAYA/myProject/assets/testFolder/test_01.ma
#print a[:-3]
x,y = a[-5:-3]  #result: x = 0, y = 1
x = int(x)      
y = int(y)
if y < 9:
    y += 1      #result: x = 0, y = 2
    #print (y)
elif y == 9:
    y = 0 
    x += 1      
x = str(x)
y = str(y)
b = a.replace(a[-5:-3], x+y)  #replace 01 with 02
#print b
cmds.file (rename = b)  #this is where I got the error. the result should be D:/DATA/MAYA/myProject/assets/testFolder/test_02.ma

【问题讨论】:

  • 更新:我刚刚尝试手动升级到 fileName_02(第一个是 fileName_01)并且脚本运行了。有人知道吗?

标签: python file rename maya


【解决方案1】:
# Error: RuntimeError: file <maya console> line 1: An invalid path was specified.

运行cmds.file(rename=your_path) 时会触发此错误,但提供的路径的目录不存在,这是有道理的,因为它无效

所以你所要做的就是在调用它之前创建文件夹。您可以为此使用os.makedirs。您不想在完整路径中包含文件名,因此您也可以使用os.path.dirname 将其剥离。因此,与其传递"/my/full/path/file_name.mb",不如使用os.path.dirname 将其剥离为"/my/full/path"

因此扩展 itypewithmyhands 的答案将如下所示:

import os

newVersion = getNextVersion()
versionFolder = os.path.dirname(newVersion)
if not os.path.exists(versionFolder):
    os.makedirs(versionFolder)

【讨论】:

  • 非常感谢 Green Cell。脚本现在运行,但我仍然想知道这怎么会发生。我从 Maya 项目设置中设置了一个项目,并且确定它确实创建了一个名为 assets 的文件夹,我可以在其中存储我在那里获得的所有资产,但它仍然告诉我路径不存在?
  • 如果你去 FIle>Set project 它看起来好像没有创建子目录,所以我猜也许它只是没有被创建?或者您可能想要仔细检查并打印出您尝试将新版本保存到的最终路径。也许它不小心指向了别处。
  • 这不是D:/DATA/MAYA/myProject/assets/testFolder/ 我要保存到的最终路径吗?因为当我查询当前文件的扩展名时,在我的代码中是 var a,它返回了D:/DATA/MAYA/myProject/assets/testFolder/test_01.ma。而且我认为我没有对路径进行任何更改,玛雅就像突然没有意识到路径一样:))
  • 我的猜测是 testFolder 不存在所以它会抛出这个错误。
  • 它确实存在于我的驱动器中。 test_01.ma 也在其中。我只是不明白 Maya 是直接使用路径还是将其理解为其他内容并导致错误?
【解决方案2】:

下面的方法非常冗长,因为我使用的是字符串操作而不是正则表达式。希望这能让你更容易阅读,但我建议只要你觉得足够舒服就改用正则表达式。

请注意,处理字符串格式以重命名场景的函数将使用最少 2 位数字(01、02 等)和最多 3 位数字(100、101 等)。如果超过 999 次迭代,则需要稍作修改。

注意: 这种方法依赖于文件版本之前的下划线(例如_01.mb),而不是当前的字符串索引方法。

import maya.cmds as cmds

def getNextVersion():
    curName = cmds.file(query=True, expandName=True) # eg. D:/yourScene_01.mb
    curVersionFull = curName.split('_')[-1]          # eg. 01.mb
    versionExtension = curVersionFull.split('.')     # eg. ['01', 'mb']
    curVersionNum = int(versionExtension[0])         # eg. 1
    extension = versionExtension[1]                  # eg. 'mb'

    nextVersionNum = curVersionNum + 1               # increment your version
    if nextVersionNum < 100:
        nextVersionFull = '{:02d}.{}'.format(nextVersionNum, extension) # eg. 02.mb
    else:
        nextVersionFull = '{:03d}.{}'.format(nextVersionNum, extension) # eg. 100.mb

    newName = curName.replace(curVersionFull, nextVersionFull)
    return newName


cmds.file(rename=getNextVersion())
cmds.file(save=True)

更新:

您已经接受了另一个答案,我相信您的问题的核心是 @green-cell 所描述的。至于这怎么可能,我真的不知道。 Maya 通常不会让您保存到不存在的文件夹中。

例如:

import maya.cmds as cmds
cmds.file(rename="D:/doesntexist/somefile.mb")
# Error: An invalid path was specified. : D:/doesntexist/
# Traceback (most recent call last):
#   File "<maya console>", line 2, in <module>
# RuntimeError: An invalid path was specified. : D:/doesntexist/ # 

无论如何,我在这里为您整理了一个更全面的功能。请注意,很难满足所有可能的文件名模式,特别是如果允许用户在过程的任何部分指定自己的文件名。这次我使用regular expressions,这使您的替换更加健壮(尽管远非万无一失)。

import re
import os
import maya.cmds as cmds

def getNextVersion(createDir=True):
    '''Find next available filename iteration based on current scene name

    Args:
        createDir (bool, optional): True to create the output directory if required. False to leave as-is (may trigger a failure)

    Returns:
        str|None: Full file path with incremented version number. None on failure
    '''

    # Grab current filename. This always returns something. If unsaved, it will return something unsavory, but still a string
    curFile = cmds.file(query=True, expandName=True)
    print('Current filename is {}'.format(curFile))

    # This matches a digit between 1 and 4 numbers in length, followed immediately by a file extension between 2 and 3 characters long
    m = re.match(r'(.+?)(\d{1,4})\.(\w{2,3})', curFile)
    if m == None:
        print('Failed at regex execution. Filename does not match our desired pattern')
        return None

    # Extract regex matches
    basePath = m.group(1)
    version = m.group(2)
    extension = m.group(3)

    # Failsafe. Should not trigger
    if not basePath or not version or not extension:
        print('Failed at failsafe. Filename does not match our desired pattern')
        return None

    # Increment file version
    numDigits = len(version)
    newFile = None
    try:
        version = int(version) + 1

        # Deal with padding
        newLength = len(str(version))
        if newLength > numDigits:
            numDigits = newLength

        # Compile new path
        newFile = '{base}{ver:{numDig:02d}d}.{ext}'.format(base=basePath, ver=version, numDig=numDigits, ext=extension)
    except Exception as e:
        print('Error parsing new version for path {}: {}'.format(curFile, e))
        return None

    # Another failsafe
    if not newFile:
        print('Failed at failsafe. Filename calculations succeeded, but new path is not valid')
        return None

    # Create output dir if needed
    dirname = os.path.dirname(newFile)
    if createDir and not os.path.isdir(dirname):
        try:
            os.makedirs(dirname)
            print('Created all dirs required to build path {}'.format(dirname))
        except Exception as e:
            print('Error creating path {}: {}'.format(dirname, e))
            return None

    return newFile


nextVersion = getNextVersion()
if not nextVersion:
    cmds.error('Error parsing new filename increment. Please see console for more information')
else:
    cmds.file(rename=nextVersion)
    cmds.file(save=True)

【讨论】:

  • try-except 子句中抛出getNextVersion() 可能是个好主意,以防您处理的场景名称不符合您的模板。
  • 嗯,非常感谢您的接近方式。它在某些情况下运行良好,但不幸的是:(当我使用 *_01 文件类型运行脚本时,我仍然收到“指定了无效路径”错误(我的意思是该错误仅发生在第一个版本 01 中。如果我将文件保存为 *_02 错误消失了。如果我尝试过第一个版本是 *_00,然后我将其重新保存为 *_01,那么它也可以正常工作)。你对此有任何想法吗?谢谢为了帮助我!!!
  • 不用担心。我现在更新了我的答案以说明使用正则表达式,希望它有意义。至于为什么你在第一次保存时偶尔会失败,我真的不知道,但我相信这与@green-cell 提到的不存在的所需目录有关
  • 要创建正则表达式,使用像regexr.com这样的工具会很有用
  • 不客气。正则表达式可能有点令人困惑,而且我远非资深人士。使用我上面链接的网站,它会在您输入时向您解释您的表达方式,并为您提供常用运算符的备忘单
【解决方案3】:

更新#02:

我意识到该错误仅发生在第一个版本中。假设我有第一个版本作为 sceneName_01.ma 并尝试对其进行版本升级并保存它,Maya 会告诉我“指定了无效路径”。但是如果我手动将其重命名为sceneName_02.ma并再次重新运行代码,代码将正常工作。

这不是因为版本的数量。一旦我尝试将我的第一个版本保存为 sceneName_00.ma 并尝试脚本,它仍然给了我同样的错误。我不得不手动将其重命名为 sceneName_01.ma 并重新运行脚本,直到它工作为止。

【讨论】:

    猜你喜欢
    • 2020-07-26
    • 1970-01-01
    • 2017-04-10
    • 1970-01-01
    • 2023-03-18
    • 2018-09-29
    • 1970-01-01
    • 2020-05-17
    • 1970-01-01
    相关资源
    最近更新 更多