2013-03-20 85 views
0

我們已經一個動態的文件夾結構的語法設置,如:查找文件夾備份基於預定義的文件夾結構

:projectRoot:/dev/model/:parentHierarchy:/:assetName:/data/obj 
:projectRoot:/dev/model/:parentHierarchy:/:assetName:/data/fbx 
:projectRoot:/asset/shots/:parentHierarchy:/animation/:assetName:/scenes 
:projectRoot:/asset/shots/:parentHierarchy:/rendering/:assetName:/scenes 

如果兩個冒號之間的話「:」是變量。現在基於單個路徑,我想檢索projectRoot,parentHierarchy和assetName。

projectRoot變量和parentHierarchy變量允許存在一個或多個文件夾,因此它可以保存子文件夾。 assetName變量僅限於一個文件夾。這些是我在下面看到的嘗試中定義的。

所以我們可以說我通過:

C:/Projects/foo/dev/model/props/furniture/couch/data/ 

這應返回:

projectRoot = C:/Projects/foo/ 
parentHierarchy = props/furniture 
assetName = couch 

然後我們還可以檢查所有規則集中定義的路徑是否存在(但相對容易):

C:/Projects/foo/dev/model/props/furniture/couch/data/obj 
C:/Projects/foo/dev/model/props/furniture/couch/data/fbx 
C:/Projects/foo/asset/shots/props/furniture/animation/couch/scenes 
C:/Projects/foo/asset/shots/props/furniture/rendering/couch/scenes 

這是我目前的測試實現:

import os 
import re 

variableRegex = re.compile(":[\w]*:") 

def getRules(): 
    return [":projectRoot:/dev/model/:parentHierarchy:/:assetName:/data/obj", 
      ":projectRoot:/dev/model/:parentHierarchy:/:assetName:/data/fbx", 
      ":projectRoot:/asset/shots/:parentHierarchy:/animation/:assetName:/scenes", 
      ":projectRoot:/dev/model/:parentHierarchy:/:assetName:/data/obj"] 

def getVarRules(): 
    """ 
     These rules define how many hierarchy depth each variable represents. 
     (This is simplified from the actual code I'm working with to ease the example for the question) 

     -1 defines that the variable can hold one or more folders (nested folders), thus never zero 
     1 defines it will can't have subfolders and will define a single folder 
    """ 
    return {":projectRoot:": -1, 
      ":parentHierarchy:": -1, 
      ":assetName:": 1} 

def reversePath(path, rule): 
    """ 
     Returns the variables within rule by getting them from the path. 
     This will only work if the given path is valid for the given rule. 

     This is currently a dummy function. 
     This is a part where I get stuck. How to slice it up based on the rules? 
    """ 
    varHierarchyDepth = getVarRules() 
    return path 

def reverseEngineerWorkspaces(path): 
    """ 
     This function should check if the given path is valid for any of the rules. 

     Note that static parts (end parts of the rule not defined by a variable) may be omitted from the input path. 
     That input path can still be validated (only if the folder exists and contains the required static end as 
     subdirectories/files.) 
    """ 
    rules = getRules() 
    varHierarchyDepth = getVarRules() 

    path = os.path.realpath(path) 
    path = path.replace("\\","/") # force forward slashes so it's similar to our rules definitions. 
    path = path.rstrip("/")   # remove any trailing slashes 

    for rule in rules: 
     # 1. 
     # First we check if any of the static parts that are in front of the last variables are present in the path. 
     # If not present it certainly isn't the correct path. 
     # We skip checking the end static part because we could easily check whether those exist within the current folder 
     staticParts = [ part for part in variableRegex.split(rule) if part != "" and part != "/" ] 
     if not all([x in path for x in staticParts[:-1]]): 
      continue 

     if rule.endswith(staticParts[-1]): 
      # If this this rule ends with a static part we can use that to check if the given path is fully valid 
      # Or if the path concatenated with that static part exists. If so we have a valid path for the rule. 
      if path.endswith(staticParts[-1]): 
       return reversePath(path, rule) 
      else: 
       lastPartSubfolders = staticParts[-1].split("/") 
       for x in range(len(lastPartSubfolders)): 
        tempPath = os.path.join(path, *lastPartSubfolders[:-x]) 
        if os.path.exists(tempPath): 
         return reversePath(tempPath, rule) 
     else: 
      raise NotImplementedError("There's no implementation for rules without a static end part.") 

print reverseEngineerWorkspaces("""C:/Projects/foo/dev/model/props/furniture/couch/data/""") 
print reverseEngineerWorkspaces("""C:/Projects/foo/dev/model/props/furniture/couch/data/fbx""") 
print reverseEngineerWorkspaces("""C:/Projects/foo/dev/model/props/furniture/couch/data/obj""") 
print reverseEngineerWorkspaces("""C:/Projects/foo/asset/shots/props/furniture/animation/couch/scenes""") 

目前它只找到由靜態部分組成的路徑(不檢查變量規則,我不知道如何在這裏添加)。

而且它不會從遵循該規則的任何完整路徑解析出變量。

+0

您可以使用字符串拆包做到這一點。 – 2013-03-20 18:48:44

+0

@Asad:你能舉個例子嗎? – 2013-03-20 18:52:12

+0

對不起,我猜得太早。很明顯python沒有'formatf'的'scanf'類似'inverse'。 – 2013-03-20 19:17:48

回答

1

我想你可以用一個正則表達式做這一切:

In [24]: re.search(r'(.+)(?:dev/model/|asset/shots/)(.+)/(.+?)(?:/data|/scenes)', path).groups() 
Out[24]: ('C:/Projects/foo/', 'props/furniture', 'couch') 
+0

我一直在尋找那樣的東西!它並不完全像我想要的那樣安全,但根據規則我可以​​創建一個適合該場景的正則表達式。這是一個很好的例子。我必須現在就跑,當我回家的時候肯定會檢查一下我是否可以使用它。謝謝! – 2013-03-20 18:48:23