2

У меня есть каталог a\ содержащий файлы и подкаталоги, которые я хочу скопировать в путь b\ где вместо копирования файлов я хочу выполнить вызов MKLINK <link> <target> для каждого файла в новый путь, а не выполнение фактической копии.

Так что, если у меня есть каталог:

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

И я копирую ссылки из пути a\ to b\ результат будет выглядеть так:

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

Иерархия каталогов должна быть сохранена как папки без ссылок, если целевой каталог не имеет соответствующей структуры папок. Обратите внимание, что только файлы являются ссылками.

Успешный тест завершится успешно, где Z:\b - пустой каталог, Z:\b содержит папку Z:\b\some_path , и любые предыдущие тесты, но Z:\b my уже содержат файлы с тем же именем; конфликты игнорируются, и для них не создается ссылка.

Как я могу сделать это, используя командный файл без каких-либо дополнительных зависимостей, кроме того, что доступно в стандартной установке Windows 10?

3 ответа3

2

Эмуляция рекурсивной структуры файлов и папок с помощью MKLink

Примечание. Это работает с уже существующей целевой папкой корневого уровня.

Вы можете использовать цикл for /d и выполнять итерации корневых подпапок первого уровня в исходном каталоге, а затем использовать команду mklink с параметром /D для создания символических ссылок каталога, чтобы связать эти подпапки в корневом каталоге целевого пути. создавая эмулированную структуру каталогов под каждым, как вам нужно, с файлами под каждым из них также рекурсивно ссылаются - целевая папка корневого уровня уже может существовать с этим методом.

Затем можно использовать цикл for для итерации файлов первого уровня в исходном каталоге, а затем соответствующим образом использовать команду mklink, чтобы создать их как прямые символические ссылки в корне целевого каталога, и целевая папка корневого уровня уже может существовать с этим методом тоже.


Пакетный скрипт

@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

Результаты


Дополнительные ресурсы

  • FOR /D
  • ЗА

  • Пакетные замены (ЗА /?)

    Кроме того, была улучшена замена ссылок на переменные FOR. Теперь вы можете использовать следующий необязательный синтаксис:

    %~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.
    
0

Создание символических ссылок с помощью MKLink из одной структуры папок в другую рекурсивно, но только для файлов, которые еще не существуют в целевом каталоге

Примечание. Приведенные ниже решения будут пропускать создание символических ссылок на файлы в целевой папке из источника, если такое же имя файла уже существует в целевой папке.Он также создаст подпапки целевого пути, которые еще не существуют, если необходимо создать символическую ссылку.


1. Пакетный скрипт (чистая партия)

Ниже приведено чистое решение для пакетного сценария, использующее цикл for /r с setlocal enabledelayedexpansion и переменными подстроками для получения повторного полного пути к файлу и имен каталогов из исходного местоположения. Это устанавливает дополнительные переменные из этих значений, анализируя исходный корневой путь из строки, а затем объединяет целевой корневой путь обратно к строке, которая будет использоваться для создания символических ссылок соответственно в соответствии с вашими требованиями и приведенной выше самой заметкой.

Важное замечание : Важно понимать количество символов в значении переменной пути SrcRoot= чтобы можно было задать номер подстроки переменной, чтобы пропустить то же количество символов в этой строке, чтобы проанализировать его, чтобы его можно было заменить на TargetRoot= значение переменной вместо.

Например: Z:\a - это ровно 4 символа, где Z , : , \ , a каждый считается как 1 символ. В итоге это всего 4; таким образом, здесь ~4 вступает в игру в !oDir:~4! и !oFile:~4! части логики в цикле. Таким образом, каждый буквенный символ в значении SrcRoot будет считаться как 1, поэтому суммируйте их и заменяйте число после тильды (~<#>) им.

@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. Пакетный скрипт (с PowerShell)

Ниже приводится решение пакетного сценария с использованием для / г цикла вложен в течение / ф цикл , чтобы получить имя переменного из динамически созданного и исполняемого скрипта PowerShell с переменными , передаваемым в соответствии с этим, чтобы затем обработать с помощью замены метод , чтобы заменить исходный путь с целевой путь, чтобы затем создать символические ссылки в соответствии с вашими требованиями и вышеупомянутой верхней заметкой.

@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

Дополнительные ресурсы

0

Эмуляция рекурсивной структуры файлов и папок с помощью MKLink

Примечание. Это будет работать только в том случае, если целевая папка пути еще не существует.

Вы можете просто использовать команду mklink с параметром /J для создания соединения каталога, указывающего связанный путь к местоположению корневого каталога источника, связывающего их и создающего эмулированную структуру каталогов, как вы хотите, с рекурсивными ссылками на файлы.


Пакетный скрипт

@ECHO ON

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

PAUSE
EXIT

Результаты


Дополнительные ресурсы

  • 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.
    

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .