• Администрация SafeZone приветствует вас на нашем форуме!
    Если вы больше не желаете видеть рекламу при просмотре тем и сообщений - то достаточно просто зарегистрироваться. Для зарегистрированных пользователей реклама не отображается.

[CMD] Создание симлинков к папкам

qawsed22

Новый пользователь
Сообщения
9
Симпатии
0
#1
// Перенесено из темы: https://safezone.cc/threads/cmd-poisk-i-peremeschenie-fajlov-po-maske.31211/

Привет, ребята и девчата!
Я извиняюсь, что влез, но не люблю плодить лишние темы, а у меня нужда сходная с той, что просил ТС.
задача:
Выбрать папки с определенным названием из многоуровневой структуры папок диска
и положить эти папки в виде символических ссылок в определенную папку назначения, сохранив структуру папок верхнего уровня.

Например, принцип формирования папок следующий:
Диск:\ПУТЬ\Работа\Заказчик\Дата\

Я в настройках скрипта задаю откуда начинать (Диск:\ПУТЬ\), какое название искать (например "Водитель") и папку назначения, куда складывать.

И в результате обработки этой структуры

D:\Работа\Заказчик1\Дата1\Сервис\...
D:\Работа\Заказчик1\Дата1\Операции\...
D:\Работа\Заказчик1\Дата1\Водитель\...

мы должны
получить следующее в папке назначения:

D:\Экспедиция\Заказчик1\Дата1\(содержимое папки "Водитель")

По прошествии определенного времени у нас в назначении получится примерно следующее:
D:\Экспедиция\Заказчик1\Дата1\(содержимое папки "Водитель" из источника "Заказчик1\Дата1\")
D:\Экспедиция\Заказчик1\Дата2\(содержимое папки "Водитель" из источника "Заказчик1\Дата2\")
D:\Экспедиция\Заказчик1\Дата3\(содержимое папки "Водитель" из источника "Заказчик1\Дата3\")
D:\Экспедиция\Заказчик2\Дата1\(содержимое папки "Водитель" из источника "Заказчик2\Дата1\")
D:\Экспедиция\Заказчик2\Дата2\(содержимое папки "Водитель" из источника "Заказчик2\Дата2\")

То есть выборка содержимого определенного каталога в месте назначения с сохранением относительного пути. Только в назначении предпоследняя папка пути до "Водитель" (в примере это "Дата1") должна стать символьной ссылкой на папку "Дата1\Водитель"

Вот это принцип "Заказчик1\Дата" - он неизменный. Разве что могут добавится промежуточные звенья. И в назначении нужно сохранить весь путь от "Заказчика" до "Дата", создать в назначении этот путь, а в папку "Дата" положить все файлы из подпапки "Водитель". Причем положить символическими ссылками для экономии места и удобства синхронизации.
С "работой" работает человек, который ведет всё продряд. В том числе и складывает себе данные по "Водитель" в соответствующую папочку. Нужно автоматизировать передачу данных о "водитель" для другого человека, который занимается обработкой именно этих данных.
За счет символических ссылок упрощается задача синхронизации: все наработки второго человека автоматически будут лежать и у первого. То есть первый кладет сырцы по "водитель" и запускает этот скрипт. Скрипт добавляет эти сырцы в назначение. Далее, назначение через облако синхронизируется со вторым человеком путем двусторонней синхронизации. И по результату, за счет двусторонней синхронизации и жестких ссылок - первый человек получил все изменения, произведенные вторым человеком.
Можно обойтись без проверки наличия существующих ссылок, если это не повредит уже существующим файлам и папкам. Я не уверен, так как не имею опыта работы с символьными ссылками! По сути, папок в источнике несколько десятков, ну пусть даже сотен вместе со вложенными. Скрипт будет работать пару секунд, так что проверка не принципиальна! Но можно и сделать!
Извините, за некоторую сумбурность описания!
Готов материально вознаградить за потраченное на меня время!
Спасибо! Извините, если помешал или нарушил что-то! Хотел как лучше! Я без злых намерений )
 
Последнее редактирование модератором:

Dragokas

Very kind Developer
Команда форума
Супер-Модератор
Разработчик
Клуб переводчиков
Сообщения
5,816
Симпатии
5,685
#2
Здравствуйте, @qawsed22!
Добро пожаловать на SafeZone!

Извините, за некоторую сумбурность описания!
Да вроде всё понятно и максимально доходчиво.

Можно обойтись без проверки наличия существующих ссылок, если это не повредит уже существующим файлам и папкам.
Если я правильно помню, при выполнении действия (копирование / удаление) над символьными ссылками, затронуты будут только они, а не оригинальные данные.
А если создавать жесткие ссылки, то действие выполняется над оригинальными данными.
Ссылка зависит от вида ключа, который вы задаете в mklink - /D или /H
EDIT. P.S. Только вот сейчас попробовал, у меня в обоих случаях идёт работа с самой ссылкой.

Кроме того, нужно знать, что:
- симлинки не поддерживаются на файловых системах FAT/FAT32
- для создания симлинков в Windows Vista/7/8.1 требуются повышенные привилегии (на Win10 начиная с 14972 подойдут права обычного юзера).
- поэкспериментировать с разными симлинками через граф. интерфейс можно, установив Hard Link Shell Extension

CMD/BATCH:
@echo off
SetLocal EnableExtensions
cd /d "%~dp0"

:: Исходная папка
set "srcFolder=c:\2\Работа"

:: Целевая папка
set "dstFolder=c:\2\Экспедиция"

:: Искомое имя папок (точное совпадение)
set "SearchFolder=Водитель"

echo Внимание! Для работы скрипта, возможно, потребуются повышенные привилегии.

for /D /R "%srcFolder%" %%d in ("%SearchFolder%*") do if /i "%%~nxd"=="%SearchFolder%" call :MakeLink "%%~dpd"

pause

goto :eof

:MakeLink
  :: src - источник
  :: dst - цель
  set "dst=%~1"
  call set "src=%%dst:%srcFolder%\=%%"
  set "src=%dstFolder%\%src%"
  2>NUL md "%src%"
  set "src=%src%%SearchFolder%"
  set "dst=%dst%%SearchFolder%"
  mklink /D "%src%" "%dst%"
exit /b
Батник сохранить в кодировке OEM-866.
 

qawsed22

Новый пользователь
Сообщения
9
Симпатии
0
#3
@Dragokas, большое спасибо! Почти то, что нужно!
Для пробы натравил скрипт на папку "C:\Users" для поиска "log" (вместо водитель) и результат положил в "C:\tmp\__"
В назначении скопировались пути, начиная от "C:\Users".
Не знаю как сформулировать правильно, но хотелось бы, чтобы в назначении вот этот симлинк на "log" был назначен на папку "MobileBrServ":

1534192073788.png
То есть в назначении мы должны "опустить" вложенность на один уровень. Если, конечно, такое возможно.
Просто по результату второму работнику придется залазить в "очищенную" папку "ДатаN", в которой будет находится только папка "Водитель" в виде симлинка. А хотелось бы, чтобы содержимое "Водитель" было доступно уже при заходе в "ДатаN" в месте назначения.
p.s. чесс слово, я очень удивлен оперативностью и лаконичностью кода. Сам не сильно понимаю, но вижу, что невероятно кратко и четко! Очень хочу отблагодарить )
 

Dragokas

Very kind Developer
Команда форума
Супер-Модератор
Разработчик
Клуб переводчиков
Сообщения
5,816
Симпатии
5,685
#4
Таки прозевал.
Замените подпрограмму на такую:

CMD/BATCH:
:MakeLink
  :: src - источник
  :: dst - цель
  set "dst=%~1"
  call set "src=%%dst:%srcFolder%\=%%"
  set "src=%dstFolder%\%src%"
  set "src=%src:~,-1%"
  for %%a in ("%src%") do set "srcP=%%~dpa"
  2>NUL md "%srcP%"
  set "dst=%dst%%SearchFolder%"
  mklink /D "%src%" "%dst%"
exit /b
Очень хочу отблагодарить )
https://safezone.cc/threads/zhelajuschim-podderzhat-proekt.1772/
 

qawsed22

Новый пользователь
Сообщения
9
Симпатии
0
#5
Невероятно, какие возможности дают казалось бы простые командные файлы! Удивительно!
Спасибо огромное! По ссылке сходил, процедуру совершил ) Надеюсь прилетело по адресу. Просто в инструкции просто номер, а сбер требует в формате R#. Добавил к номеру в инструкции букву R, платеж прошел.
 

qawsed22

Новый пользователь
Сообщения
9
Симпатии
0
#6
Как выяснилось, Synology нее поддерживает симлинки ((
А реально ли сделать подобный функционал, только без симлинков?
Т.е. сначала копируются файлы и папки из источника в назначение, заменяя более новыми в случае наличия оных. А после проводится обратная операция.
Сыть в следующем: при помощи облака синхронизируются два рабочих места.
То есть на первоисточнике зарождается основная файловая структура. Далее, первоисточник, двусторонней синхронизацией отправляет это на облако через отдельную структуру папок (отдельная структура нужна чтобы у второго работника были только необходимые ему для работы файлы).
На другой стороне сидит "приемник", который также посредством двусторонней синхронизации получает новые файлы.
Но так как "приемник" генерит и свои файлы в соответствующих папках, то нужен механизм, который позволит обеим сторонам работать в своих структурах папок,
а вся синхронизация для них чтобы происходила прозрачно. Если приемник выложит некий новый файл, то программа синхронизации автоматически обновит папку назначения, а доработанный скрипт просто положит оттуда в соответствующую папку источника. Тем самым на первоисточнике процесс также будет прозрачным и ненужно будет руками перебирать файлы
Если бы синхронизация поддерживала бы симлинки, то проблем бы небыло. А так как она не поддерживает, то нужно обеспечить процесс автоматического добавления файлов, что нагенерила принимающая сторона в первоначальную папку.
Если просто сделать двустороннюю синхронизацию, то для "приемника" станут доступны абсолютно все файлы первоисточника, а это ненужно. Приходится реализовывать через вот эту отдельную файловую структуру.

Если кто умеет Rsync'ом подобное реализовать - буду рад помощи. Я не разобрался во всех ключах и премудростях
Спасибо!
 
Последнее редактирование:

Dragokas

Very kind Developer
Команда форума
Супер-Модератор
Разработчик
Клуб переводчиков
Сообщения
5,816
Симпатии
5,685
#7
Synology - это что, NAS? На основе какой файловой системы они работают? Все современные должны поддерживать.

@qawsed22, а обычные ярлыки к папкам не подойдёт взамен симлинкам?
 

qawsed22

Новый пользователь
Сообщения
9
Симпатии
0
#8
Да, это NAS. Должен, но не поддерживает ( тупо игнорирует все симлинки. И джункшены - тоже игнорирует.
Сейчас нарыл программу, которая вроде как по заявлениям умеет. Ставлю, пробую.
 

Dragokas

Very kind Developer
Команда форума
Супер-Модератор
Разработчик
Клуб переводчиков
Сообщения
5,816
Симпатии
5,685
#9
Так может дело в путях, нужно прописывать в качестве цели симлинка относительный путь, а не полный.
У вас какой полный путь к файлу на NAS, через букву диска или через \\Имя ПК
Если запустить консоль с повышенными привилегиями, перейти командой cd в каталог NAS и затем создать произвольный симлинк командой:
Код:
mklink /D AAA BBB
что пишет в ответ консоль?
 

qawsed22

Новый пользователь
Сообщения
9
Симпатии
0
#10
на Синелоге внутрях симлинки наверняка работают. Потому что Synology работает на Debian.
Но я синхронизацию делаю через их отдельное приложение. А это приложение игнорирует симлинки в папке источника и не кладет их к себе.
Она не умеет с ними работать.
 

Dragokas

Very kind Developer
Команда форума
Супер-Модератор
Разработчик
Клуб переводчиков
Сообщения
5,816
Симпатии
5,685
#11
Потому что Synology работает на Debian.
ОС значения не имеет. Имеет значение тип файловой системы.
Но если это синхронизация через стороннее ПО, то это бага данного ПО. Советую написать в их ТП.
Но даже если бы синхронизировалось, симлинки нужно делать с относительными ссылками, иначе они побьются после синхрона.
А может как раз из-за этого ПО их игнорирует. Но это вряд ли.
Попробуйте вариант с ярлыками.
 

qawsed22

Новый пользователь
Сообщения
9
Симпатии
0
#12
Попробуйте вариант с ярлыками
не, это не вариант.
ну тут уж ниче не попишешь. Маемо, шо маемо! :Pardon:
А можно ведь сделать простое копирование без симлинков с понижением уровня папок, а второй процедурой - обратный процесс, т.е. из назначения в источник с повышением уровня, пропуская старые файлы?
Или это не возможно? Спасибо!
 

qawsed22

Новый пользователь
Сообщения
9
Симпатии
0
#13
@Dragokas, пришла мне в голову замечательная мысль как обмануть и Синолоджи и дядюшку Билла одновременно ))
А что если делать все тоже самое, но без симлинков, но добавить создание симлинков в обратную сторону? Т.е. симлинк будет именно в источнике! То есть мы скопируем из папки источника "...\Дата1\Водитель" в папку назначения "...\Дата1", но создадим симлинк из папки назначения "...\Дата1" на папку источника "...\Дата1\Водитель". При этом, если такое возможно, вначале работы скрипта указать, чтобы он не трогал симлинки в источнике. Если опознать симлинк не просто средствами командного файла, то можно имеющиеся в симлинке файлы переносить с заменой, удалять симлинк и воссоздать его заново.
Я повторюсь, я не сильно разбираюсь в логике работы команд копирования при встрече с симлинками. Да, мой алгоритм предполагает излишнюю нагрузку на шевеление файлами. Но в моем случае - это не принципиально ввиду не очень большого количества обрабатываемой информации.
Мне кажется, что это простое и лаконичное решение внезапно образовавшейся проблемы )
Спасибо!
Помогите, пожалуйста, правильно составить. Откровенно говоря я не могу понять логику сокращений этих хитрых )
 

Dragokas

Very kind Developer
Команда форума
Супер-Модератор
Разработчик
Клуб переводчиков
Сообщения
5,816
Симпатии
5,685
#14
А можно ведь сделать простое копирование без симлинков с понижением уровня папок, а второй процедурой - обратный процесс, т.е. из назначения в источник с повышением уровня, пропуская старые файлы?
Можно. Командой robocopy.

А что если делать все тоже самое, но без симлинков, но добавить создание симлинков в обратную сторону? Т.е. симлинк будет именно в источнике!
Вам лучше знать.
Расширение для контекстного меню я вам дам выше, которым можно симмитировать все нужные симлинки.
Остальные тесты за вами.

Предпоследняя строка скрипта у вас есть: mklink /D "%src%" "%dst%"
src - где создавать симлинк (у вас он создаётся на стороне получателя), dst - куда он будет перемещать. Дальше можете менять как угодно.

Нужно скопировать с источника в получатель. Удалить источник. И заменить источник на симлинк к получателю, Делаете через robocopy или xcopy:
Код:
xcopy /c /e /h /r /y /i /k "%dst%" "%src%"
rd /s /q "%dst%"
mklink /D "%dst%" "%src%"
P.S. Не проверял.
Пропуск устаревших файлов - это один из ключей, если копировать через robocopy /? - вызов справки. В нашем разделе есть статья.
 

qawsed22

Новый пользователь
Сообщения
9
Симпатии
0
#15
Спасибо, буду колдовать. Сегодня даже до Русиновича добрался, пытаясь нарыть ключи хитрые, которые могут помочь.
Буду пробовать. Спасибо!
 
Сверху Снизу