Como analisar um diretório recursivamente e MKLINK cada arquivo em um caminho de destino com a mesma estrutura de árvore

2

Eu tenho um diretório a\ contendo arquivos e subdiretórios que eu quero copiar para o caminho b\ onde, em vez de copiar os arquivos, eu quero executar uma chamada para MKLINK <link> <target> em cada arquivo para o novo caminho do que realizar uma cópia real.

Então, se eu tiver um diretório:

Z:\a\file1.txt
Z:\a\file2.txt
Z:\a\some_path\file3.txt
Z:\a\some_path\file4.txt

E eu copio os links do caminho a\ para b\ e o resultado será:

Z:\b\file1.txt           <<===>> z:\a\file1.txt
Z:\b\file2.txt           <<===>> z:\a\file2.txt
Z:\b\some_path\file3.txt <<===>> z:\a\some_path\file3.txt
Z:\b\some_path\file4.txt <<===>> z:\a\some_path\file4.txt

A hierarquia de diretórios deve ser preservada como pastas sem link, caso o diretório de destino não tenha uma estrutura de pastas correspondente. Note que apenas os arquivos são links .

Um teste bem-sucedido será bem-sucedido, onde Z:\b é um diretório vazio, Z:\b contém uma pasta Z:\b\some_path e testes anteriores, mas Z:\b meu já contém arquivos com o mesmo nome; conflitos são ignorados e nenhum link é criado para eles.

Como posso fazer isso usando um arquivo em lotes sem dependências adicionais além do que está disponível em uma instalação padrão do Windows 10?

    
por Zhro 22.06.2018 / 01:44

3 respostas

2

Emulando uma estrutura de arquivos e pastas recursiva com MKLink

Note: This works with an already existing root level target folder.

Você pode usar um loop para / d e iterar as subpastas raiz de primeiro nível no diretório de origem e em seguida, use o comando mklink com o parâmetro /D para crie links simbólicos do diretório para vincular essas subpastas no diretório-raiz do caminho de destino, criando uma estrutura de diretórios emulada abaixo de cada um, conforme desejado, com arquivos recursivamente referenciados - a pasta de destino do nível raiz já pode existir com este método.

Você pode usar um loop para iterando os arquivos de primeiro nível dentro do diretório de origem e, em seguida, usar o mklink para criar esses links simbólicos diretos na raiz do diretório de destino, e a pasta de destino do nível raiz já pode existir com este método também.

Script em lote

@ECHO ON

SET SrcRoot=Z:\a
SET TargetRoot=Z:\b

FOR /D %%A IN ("%SrcRoot%\*") DO (
    MKLINK /D "%TargetRoot%\%%~NA" "%%~A"
    )

FOR %%A IN ("%SrcRoot%\*") DO (
    MKLINK "%TargetRoot%\%%~NXA" "%%~A"
    )

PAUSE
EXIT

Resultados

enter image description here

enter image description here

enter image description here

Mais recursos

  • FOR / D
  • PARA

  • Substituições em lote (FOR /?)

    In addition, substitution of FOR variable references has been enhanced. You can now use the following optional syntax:

    %~nI        - expands %I to a file name only
    %~xI        - expands %I to a file extension only
    
  • MKLink

  • mklink /?

    Creates a symbolic link.
    
    MKLINK [[/D] | [/H] | [/J]] Link Target
    
            /D      Creates a directory symbolic link.  Default is a file
                    symbolic link.
            /H      Creates a hard link instead of a symbolic link.
            /J      Creates a Directory Junction.
            Link    Specifies the new symbolic link name.
            Target  Specifies the path (relative or absolute) that the new link
                    refers to.
    
por 22.06.2018 / 05:49
0

Emulando uma estrutura de arquivos e pastas recursiva com MKLink

Note: This will only work if the target path folder does not already exist.

Você pode simplesmente usar o comando mklink com o parâmetro /J para criar um junção de diretório apontando o caminho vinculado para o local do diretório-raiz da origem, vinculando os dois e criando uma estrutura de diretórios emulada conforme desejado com arquivos abaixo sendo referenciados recursivamente também.

Script em lote

@ECHO ON

SET SrcRoot=Z:\a
SET LinkRoot=Z:\b
MKLINK /J "%LinkRoot%" "%SrcRoot%"

PAUSE
EXIT

Resultados

enter image description here

enter image description here

enter image description here

Mais recursos

  • MKLink
  • mklink /?

    Creates a symbolic link.
    
    MKLINK [[/D] | [/H] | [/J]] Link Target
    
            /D      Creates a directory symbolic link.  Default is a file
                    symbolic link.
            /H      Creates a hard link instead of a symbolic link.
            /J      Creates a Directory Junction.
            Link    Specifies the new symbolic link name.
            Target  Specifies the path (relative or absolute) that the new link
                    refers to.
    
por 22.06.2018 / 04:21
0

Crie links simbólicos com MKLink de uma estrutura de pastas para outra recursivamente, mas apenas para arquivos que ainda não existem no diretório de destino

Note: The below solutions will skip making symbolic links to files at target from the source if the same file name already exists at the target. It will also create the target path sub-folders that don't exist already if a symbolic link needs to be created.

1. Batch Script (pure batch)

Below is a pure batch script solution using a for /r loop with setlocal enabledelayedexpansion and variable substrings to get the iterated full file path and directory names from the source location. This sets additional variables from those values parsing the source root path from the string and then concatenates the target root path back to the string to be used to create the symbolic links accordingly as per your requirements and the above topmost note.

Important: It is important to understand the number of characters in the SrcRoot= path variable value here so you can set the variable substring number to skip that same number of characters in that string to parse it out so it can be replaced by the TargetRoot= variable value instead.

For Example: So Z:\a is exactly 4 characters where Z, :, \, and a each count as 1 character. Summed up this is 4 total; thus, this is where the ~4 comes into play in the !oDir:~4! and !oFile:~4! portions of the logic within the loop. So each literal character in the SrcRoot value will each count as 1 so sum those up and replace the number after the tilde (~<#>) with it.

@ECHO ON

SET SrcRoot=Z:\a
SET TargetRoot=Z:\b

SETLOCAL ENABLEDELAYEDEXPANSION
FOR /R "%SrcRoot%" %%A IN ("*") DO (
  SET oDir=%%~DPA
  SET oFile=%%~A
  IF NOT EXIST "%TargetRoot%!oDir:~4!" MD "%TargetRoot%!oDir:~4!"
    IF NOT EXIST "%TargetRoot%!oFile:~4!" MKLINK "%TargetRoot%!oFile:~4!" "%%~A"
  )

PAUSE
EXIT

2. Batch Script (with PowerShell)

Below is a batch script solution using a for /r loop nested into a for /f loop to get a variable name from a dynamically created and executed PowerShell script with variables passed in accordingly to then process with the replace method to replace the source path with the target path to then created the symbolic links as per your requirements and the above topmost note.

@ECHO ON

SET SrcRoot=Z:\a
SET TargetRoot=Z:\b

CALL :PowerShell

FOR /R "%SrcRoot%" %%A IN ("*") DO (
  CD /D "%PowerShellDir%"
  FOR /F "TOKENS=*" %%B IN ('Powershell -ExecutionPolicy Bypass -Command "& '%PSScript%' '"%SrcRoot%"' '"%TargetRoot%"' '"%%~A"'"') DO (
      IF NOT EXIST "%%~DPB" MD "%%~DPB"
      IF NOT EXIST "%%~B" MKLINK "%%~B" "%%~A"
      )
  )

PAUSE
EXIT

:PowerShell
SET PowerShellDir=C:\Windows\System32\WindowsPowerShell\v1.0
SET PSScript=%temp%\~tmpStrFldrRplc.ps1
IF EXIST "%PSScript%" DEL /Q /F "%PSScript%"
ECHO $Source = $args[0]>"%PSScript%"
ECHO $Dest   = $args[1]>>"%PSScript%"
ECHO $FPath  = $args[2]>>"%PSScript%"
ECHO $var    = $FPath.Replace($Source,$Dest)>>"%PSScript%"
ECHO Write-Output $Var>>"%PSScript%"
GOTO :EOF

Mais recursos

por 28.06.2018 / 04:26