Change file/folder tree structure based on name condition
<p>I've a folder/file tree like this:</p>

<pre><code>/source/photos/d831fae7-ed7f-44b1-8345-54fc54f0710f/car/1.jpg
/source/photos/20a33e40-8bb2-4ebe-b703-632115ba6714/house/
/source/photos/20a33e40-8bb2-4ebe-b703-632115ba6714/boat/b6a1b8bf-7f4c-45d6-84c1-37fbb8204328/2.jpg
/source/20dd7963-0d4a-4a80-83f8-4800de672087/music/1.mp3
/source/64e997aa-bb7e-4cdf-9348-8b8d48e2d336/music/c6a0b1d4-9d2d-4a21-bce3-8c922f8ad55b/2.mp3
/source/movies/83e760f4-7235-4d7e-bd51-56aa82192a94/572f3820-ea22-40c1-903a-31b7f412ae38/1.mp4
/source/movies/993209ed-092a-4665-a5d1-4ce537e2a680/4c200cf1-eb6b-40a7-84d7-9a2db0f75e09/1.mp4
</code></pre>

<p>To easily read the previous tree, here it is a simpler representation:</p>

<pre><code>/source/photos/uuid0/car/1.jpg
/source/photos/uuid1/house/
/source/photos/uuid1/boat/uuid2/2.jpg
/source/uuid3/music/1.mp3
/source/uuid4/music/uuid5/2.mp3
/source/movies/uuid6/uuid7/1.mp4
/source/movies/uuid8/uuid9/1.mp4
</code></pre>

<hr>

<p>I want to move the folders and files from "<code>source</code>" to the "<code>destination</code>" directory and perform a tweak in the tree structure on the fly. The resulting tree should look like this:</p>

<pre><code>/destination/photos/car/1.jpg
/destination/photos/house/
/destination/photos/boat/2.jpg
/destination/music/1.mp3
/destination/music/2.mp3
/destination/movies/1_1.mp4
/destination/movies/1_2.mp4
</code></pre>

<hr>

<p>As you can see, I want to:</p>

<ul>
<li>Ignore every <code>uuid</code> in the middle of the path; </li>
<li>When there is a conflict on file or folder name (i.e. <code>1.mp4</code>), an incremental suffix should be added (i.e. <code>1_1.mp4</code>);</li>
<li>Move empty folders (like "<code>house</code>");</li>
<li>Avoid conflicts when moving (moving a parent directory before moving its child) - it should <strong>recursively</strong> trespass the tree and move its contents.</li>
</ul>

<p>I've tried parsing the path with <code>os.walk</code> but can't accomplish this.</p>

<hr>

<p>Any ideas? Thanks!</p>

<hr>

<p><strong>NOTE:</strong> <code>uuid</code> (i.e. <code>6e56c11b-3adf-440e-96f5-375884c96c55</code>) can be checked using the following function:</p>

<pre><code>import uuid
def validate_uuid4(uuid_string):
    try:
        val = uuid.UUID(uuid_string, version=4)
    except ValueError:
        return False
    return True
</code></pre>

<hr>

<p><strong>EDIT: Example code</strong></p>

<p>The main problem is this: </p>

<p>Given the following structure</p>

<pre><code>.
âââ Icon\r
âââ folder1
    âââ d.txt
    âââ folder1.1
        âââ 64e997aa-bb7e-4cdf-9348-8b8d48e2d336
        âÂ Â  âââ a.mkv
        âââ d831fae7-ed7f-44b1-8345-54fc54f0710f
            âââ b.mkv
            âââ d831fae7-ed7f-44b1-8345-54fc54f0710f
                âââ b.mkv
                âââ c.jpg
</code></pre>

<p>with this code:</p>

<pre><code>#!/usr/bin/python
import os
import uuid

args = {}
args['rootdirOriginal'] = "/Users/xxx/Desktop/UploadDropbox"
pathString = []
pathStringClean=[]

def validate_uuid4(uuid_string):
    try:
        val = uuid.UUID(uuid_string, version=4)
    except ValueError:
        return False
    return True


for dirpath, dirs, files in os.walk(args['rootdirOriginal']):
    if files:
        for f in files:
            pathTmp = []
            pathRelative = os.path.relpath(dirpath, args['rootdirOriginal'])
            for p in pathRelative.split("/"): 
                pathTmp.append(p)
            pathTmp.append(f)   

            pathTmpClean = [x for x in pathTmp if not validate_uuid4(x) and x[0] != "." and x[0:4]!="Icon"]

            pathStringTmp = ("/").join(pathTmp)
            pathStringTmpClean = ("/").join(pathTmpClean)

            if len(pathTmp) &gt; 0:
                pathString.append(pathStringTmp)
                pathStringClean.append(pathStringTmpClean)

print pathString
print pathStringClean
</code></pre>

<p>this is the first output:</p>

<pre><code>['./.DS_Store', './Icon\r', 'folder1/.DS_Store', 'folder1/d.txt', 'folder1/folder1.1/.DS_Store', 'folder1/folder1.1/64e997aa-bb7e-4cdf-9348-8b8d48e2d336/.DS_Store', 'folder1/folder1.1/64e997aa-bb7e-4cdf-9348-8b8d48e2d336/a.mkv', 'folder1/folder1.1/d831fae7-ed7f-44b1-8345-54fc54f0710f/.DS_Store', 'folder1/folder1.1/d831fae7-ed7f-44b1-8345-54fc54f0710f/b.mkv', 'folder1/folder1.1/d831fae7-ed7f-44b1-8345-54fc54f0710f/d831fae7-ed7f-44b1-8345-54fc54f0710f/b.mkv', 'folder1/folder1.1/d831fae7-ed7f-44b1-8345-54fc54f0710f/d831fae7-ed7f-44b1-8345-54fc54f0710f/c.jpg']
</code></pre>

<p>and this is the second:</p>

<pre><code>['', '', 'folder1', 'folder1/d.txt', 'folder1/folder1.1', 'folder1/folder1.1', 'folder1/folder1.1/a.mkv', 'folder1/folder1.1', 'folder1/folder1.1/b.mkv', 'folder1/folder1.1/b.mkv', 'folder1/folder1.1/c.jpg']
</code></pre>

<p>I can't just remove the duplicates since some times they are not truly dups but, instead, should be renamed as I described before</p>

<p>Here is my ending solution (thank you Sushanta!)</p>

<pre><code>#!/usr/bin/python
import os
import uuid
from collections import Counter
import shutil

args = {}
args['rootdirOriginal'] = "/Users/xxx/Desktop/UploadDropbox"
args['uuid'] = str(uuid.uuid4())
args['rootdir'] = args['rootdirOriginal']+"/"+args['uuid']

pathString = []
pathStringClean=[]
pathStringFolder = []
toDelete = []


# Validate if string is a valid UUID
def validate_uuid4(uuid_string):
    try:
        val = uuid.UUID(uuid_string, version=4)
    except ValueError:
        return False
    return True


# Walk through "source" directory
for dirpath, dirs, files in os.walk(args['rootdirOriginal']):
    # Files
    if files:
        for f in files:
            pathTmp = []
            pathFolderTmp = []
            pathRelative = os.path.relpath(dirpath, args['rootdirOriginal'])

            for p in pathRelative.split("/"): 
                pathTmp.append(p)
                pathFolderTmp.append(p)

            # Flag every fuke   
            pathTmp.append(f+"***") 

            # Delete list elements whose name are:  a previous UUID //// starting with "." //// starting with  "Icon"
            pathTmpClean = [x for x in pathTmp if not validate_uuid4(x) and x[0] != "." and x[0:4]!="Icon"]
            pathFolderTmpClean = [x for x in pathFolderTmp if not validate_uuid4(x) and x[0] != "." and x[0:4]!="Icon"]

            # Convert to path string
            if len(pathTmpClean) &gt; 0:
                pathStringTmp = ("/").join(pathTmp)
                pathStringTmpFolder = ("/").join(pathFolderTmpClean)
                pathStringTmpClean = ("/").join(pathTmpClean)
                pathString.append(pathStringTmp)
                pathStringClean.append(pathStringTmpClean)
                if pathStringTmpFolder != "":
                    pathStringFolder.append(pathStringTmpFolder)

    # Empty directory               
    if dirs:
        for d in dirs:
            emptyDir = os.path.relpath(dirpath, args['rootdirOriginal'])
            if emptyDir == ".":
                emptyDir = d
            else:
                emptyDir =  os.path.join(emptyDir,d)

            pathStringFolder.append(emptyDir)

# Delete repeating directories          
pathStringFolder = list(set(pathStringFolder))

# Create a list with the indexes of first list when it is a directory 
for i in range(0,len(pathStringClean)):
    if (len(pathStringClean[i]) &gt; 3):
        if pathStringClean[i][-3:] != "***":
            toDelete.append(i)

# Delete indexes of both "source" and "destinantion" lists where it is directory
for i in sorted(toDelete, reverse=True):
    del pathString[i]
    del pathStringClean[i]

# Delete the flag "***"
pathString = [x[:-3] for x in pathString]
pathStringClean = [x[:-3] for x in pathStringClean]

# Rename repeated filenames - create sequential suffix
counts = Counter(pathStringClean)
for s,num in counts.items():
    if num &gt; 1:
        for suffix in range(1, num + 1):
            pathStringClean[pathStringClean.index(s)] = ("/").join(s.split("/")[:-1]) +("/")+(".").join((s.split("/")[-1]).split(".")[:-1])+"_"+str(suffix)+"."+(s.split("/")[-1]).split(".")[-1]

pathStringFolder.reverse()

# Create root "destination" directory
os.mkdir(args['rootdir'])

# Create other directories 
for folder in pathStringFolder:
    try:
        os.makedirs(os.path.join(args['rootdir'],folder))
    except:
        pass

# Move files
for i in range(0,len(pathStringClean)):
    os.rename(os.path.join(args['rootdirOriginal'],pathString[i]),os.path.join(args['rootdir'],pathStringClean[i]))

# Delete everything except root "destination" directory
for f in os.listdir(args['rootdirOriginal']):
    if (not (os.path.isfile(os.path.join( args['rootdirOriginal'],f))) and f != args['uuid']):                  
        shutil.rmtree(os.path.join( args['rootdirOriginal'],f))
</code></pre>

python path shutil