3

I have two main folders which have a lot of sub-folders in different drives. Have to create symbolic link for all files in the second folder into the first one.

C:\folderC>tree /f
C:.
├───folder1
│       file1.txt
│       file3.txt
│
└───folder2
        file1.txt
        file3.txt

D:\folderD>tree /f
D:.
├───folder1
│       file2.txt
│
└───folder2
        file2.txt

Result using 2 commands:

C:\>mklink C:\folderC\folder1\file2.txt D:\folderD\folder1\file2.txt
symbolic link created for C:\folderC\folder1\file2.txt <<===>> D:\folderD\folder1\file2.txt

C:\>mklink C:\folderC\folder2\file2.txt D:\folderD\folder2\file2.txt
symbolic link created for C:\folderC\folder2\file2.txt <<===>> D:\folderD\folder2\file2.txt

C:.
├───folder1
│       file1.txt
│       file2.txt
│       file3.txt
│
└───folder2
        file1.txt
        file2.txt
        file3.txt

How to make it for all files with a few commands instead of writing the code manually for each file?

PS: Firstly I wanted to use hard links but it seems it is not possible.

C:\>mklink /h C:\folderC\folder2\file2.txt D:\folderD\folder2\file2.txt
The system cannot move the file to a different disk drive.
2
  • Is there any way you can forego creating hard or symbolic links to accomplish what you're trying to do? Commented Nov 3, 2013 at 16:52
  • @adbertram I do not think so, because files in D were moved from C and they should be visible inside C. I try to reduce internal HDD activity by using external USB drive. Commented Nov 4, 2013 at 10:02

3 Answers 3

4

You can try something link this:

function createSymbolicLinks ($source, $destination, [switch]$recurse) {
    Get-ChildItem $source -Recurse:$recurse | ? { !$_.PSISContainer } | % {
        $destpath = $_.Fullname -replace [regex]::Escape($source), $destination
        if(!(Test-Path (Split-Path $destpath))) {
            #Create missing subfolders
            New-Item (Split-Path $destpath) -ItemType Directory -Force | Out-Null
        }
        cmd /c mklink $destpath $($_.FullName) | Out-Null
    }
}

#Create symbolic links in c:\folderC for all files in d:\folderD(with recursive search)
createSymbolicLinks -source d:\folderD -destination c:\folderC -recurse

I believe this will fail if the same filename already exists in c:\folderc. So if you need to replace a file in c:\folderc with a symbolic link from d:\folderd, you need to extend it to remove the existing file.

UPDATE: This will only go down one level with the recurseoption. It's not the prettiest solution, but it should work.

function createSymbolicLinks ($source, $destination, [switch]$recurse) {
    Get-ChildItem $source | % { 
        if($_.PSIsContainer -and $recurse) { 
            Get-ChildItem $_.FullName
        } else { 
            $_
        }
    } | ? { !$_.PSIsContainer } | % { 
        $destpath = $_.Fullname -replace [regex]::Escape($source), $destination
        if(!(Test-Path (Split-Path $destpath))) {
            #Create missing subfolders
            New-Item (Split-Path $destpath) -ItemType Directory -Force | Out-Null
        }
        cmd /c mklink $destpath $($_.FullName) | Out-Null
    }
}

#Create symbolic links in c:\folderC for all files in d:\folderD(with recursive search)
createSymbolicLinks -source d:\folderD -destination c:\folderC -recurse
Sign up to request clarification or add additional context in comments.

2 Comments

Can I limit the recursive with 1 sub-folder level?
See updated answer. I couldn't think of a better way at the moment, but it does the job I think.
2

PS: Firstly I wanted to use hard links but it seems it is not possible.

Hard links are only possible within the same filesystem: they cannot span different drives (including when using reparse points to avoid drive letters).

Second, "symbolic links" in Windows are a shell (ie. Windows Explorer) artefact. they will only work when applications make use of the shell namespace (which most do not).

Better to avoid.

1 Comment

I agree. It'd be interesting to see what the OP is trying to accomplish to see if we can think of another way to do it.
2

other way. In a .bat file, i use this :

for /f "delims=" %%i in ('dir /b /s *.jpg *.jpeg *.png *.gif') do (
    name of link = a path to a folder + a number + %%~nxi
    mklink </h for hard links or nothing for symlinks> name of link "%%i" >> log.txt
)

explanation : for /f ... loop in a chosen dir with subfolders, %%i is the name of a file found with path (folder\subfolder\one_file.ext).
%%i~nxi is the name without path (n) and with extent (x). mklink créate the link for %%i It works. My question was different. In 2 computers, i can browse all the symbolic links (all the folders and subfolders) but in the third, not exactly. But with hard links, all is OK (with mklink /H ) Read the end of my question please. Thanks

1 Comment

To make it easier to read for others, wrap your code into ``, so it looks like this. For multi line code, add 4 spaces before every line. You can read about it here. ;)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.