Компьютерный форум OSzone.net  

Компьютерный форум OSzone.net (http://forum.oszone.net/index.php)
-   Скриптовые языки администрирования Windows (http://forum.oszone.net/forumdisplay.php?f=102)
-   -   Перенос каталогов и файлов (http://forum.oszone.net/showthread.php?t=338323)

RealDT 19-12-2018 19:48 2847092

Перенос каталогов и файлов
 
Добрый день.

Друзья, необходимо выборочно перенести каталоги (и подкаталоги) и файлы в резервную папку.
Список выбранных каталогов сохранён в файле dir.txt, например:
Docs\!Каталог 1
Docs\Каталог 2
Docs\Каталог 3

Для выборочного переноса выполняется следующий код:
Код:

@echo off
cls
setlocal enabledelayedexpansion
set curdisk=%~d0
 
for /f "usebackq delims=" %%A in ("dir.txt") do (
    Set "folder_from="%curdisk%\%%A""
    set "folder_where="%curdisk%\%date:~6,4%-%date:~3,2%-%date:~0,2% reserv\%%A""
 
    if not exist !folder_where! md !folder_where!
   
    move /Y !folder_from!\*.* !folder_where!
    FOR /F "delims=" %%I IN ('DIR /B /AD !folder_from!') DO (
        move /Y !folder_from!\"%%I" %1 !folder_where!
    )
if exist !folder_from! rd !folder_from! | echo !folder_from!
)

Но если в названии выбранного каталога или в названии его подкаталогов имеется "!" (восклицательный знак), код не работает. Из названия каталогов/подкаталогов исчезает "!".

Если в файле dir.txt знак ! экранировать ^, код работает только с этим каталогом.
Docs\^!Каталог 1

Структура этого каталога может быть такой:
Docs\!Каталог 1
Docs\!Каталог 1\Папка 1!
Docs\!Каталог 1\!Папка 2
Docs\!Каталог 1\Папка !3
Docs\!Каталог 1\Папка 4
Т.е. ! знак может оказаться в любом месте в названии подкаталога и/или файлов.
Каким образом экранировать ! знак в подкаталогах и файлах этой папки? Может у кого есть другое решение по переносу заданных списком каталогов со всеми файлами?

Iska 19-12-2018 21:45 2847105

Цитата:

Цитата RealDT
Может у кого есть другое решение по переносу заданных списком каталогов со всеми файлами? »

Есть несколько вариантов. Например, не использовать отложенное раскрытие переменных окружения. Перейти на WSH/PoSH.

Зачем Вы используете здесь:
Цитата:

Код:

if exist !folder_from! rd !folder_from! | echo !folder_from!

конвеер?!

megaloman 19-12-2018 22:51 2847111

RealDT,
Цитата:

Цитата Iska
не использовать отложенное раскрытие переменных окружения »

Попытался переделать Ваш код, не знаю, что получилось (корежить чужой код - нудное неблагодарное занятие), но васклицательного знака мой код не боится.
Код:

@Echo Off
cls
        Set "curdisk=%~d0"
        For /f "usebackq delims=" %%A in ("dir.txt") Do (
                RoboCopy "%curdisk%\%%A" "%curdisk%\%date:~6,4%-%date:~3,2%-%date:~0,2% reserv\%%~nxA" "*.*" /S /IS /Move
        )
Pause

До меня совершенно не доходит строка:
Цитата:

Цитата RealDT
move /Y !folder_from!\"%%I" %1 !folder_where! »

Если моё извращение Вашего кода Вас не устраивает, объясните подробнее, что Вам надо.

RealDT 21-12-2018 12:36 2847337

Спасибо за отклики.
По порядку:

Цитата:

Цитата Iska
Перейти на WSH/PoSH »

мне такое пока не ведомо, посмотрю. если есть ссылки, просьба черкануть...

это
Код:

if exist !folder_from! rd !folder_from! | echo !folder_from!
нужно чтобы удалить выборочную папку (которая указана в dir.txt) c диска после переноса.

эта команда
Код:

move /Y !folder_from!\"%%I" %1 !folder_where!
переносит и каталоги и файлы. %1 - лишнее, можно не указывать

Цитата:

Если моё извращение Вашего кода Вас не устраивает, объясните подробнее, что Вам надо.
Предложенный Вами код работает. Но, если move переносит файлы, то robocopy их копирует. Команда move (а не copy & rd или robocopy) на физическом уровне работает в разы быстрее, поскольку работает только в секторах HDD, где размещены ссылки на содержание файлов, а не данные этих файлов. Другими словами - copy/robocopy резервирует и создаёт на диске новый блок данных, а move - только меняет ссылки на расположение этих данных. Скорость работы move и copy/robocopy хорошо видна на больших файлах и незаметна если файлов много, но они небольшого размера.

Вот код, который переносит (не копирует) один заданный каталог и обрабатывает также каталоги/файлы с восклицательными знаками:
Код:

set curdisk=%~d0
Set dir1=Docs\!КОНТАКТЫ
Set folder_from=%curdisk%\%dir1%
Set folder_where=%curdisk%\%date:~6,4%-%date:~3,2%-%date:~0,2% reserv\%dir1%
if not exist "%folder_where%" md "%folder_where%"
if exist "%folder_from%\*.*" move /Y "%folder_from%\*.*" "%folder_where%"
FOR /F "delims=" %%I IN ('DIR /B /AD "%folder_from%"') DO (move /Y "%folder_from%\%%I" %1 "%folder_where%")
if exist %folder_from% rd %folder_from%

Пока не разобрался, как в переменную dir1 в цикле вносить новое значение из файла dir.txt со списком выбранных каталогов.

Цитата:

объясните подробнее, что Вам надо.
Изначально решалось это:
Перенести избранные каталоги с их содержанием (подкаталоги и файлы) в резервную папку на текущем диске. Название диска не известно.

megaloman 21-12-2018 13:18 2847347

RealDT,
Цитата:

Но, если move переносит файлы, то robocopy их копирует.
Как говорил мой начальник, не надо ля-ля. :) Robocopy c ключом /mov переносит файлы с путями, а /move и директори, но при этом они будут удалены из источника, если только пустые. Я проверял, работает.
Проделайте robocopy /? >c:\robocopy.txt и читайте описание команды в файле c:\robocopy.txt
У меня ощущение, что Вы не проанализировали результат выполнения моего кода. Либо не точно его повторили, без всех ключей. Он полностью решает поставленную задачу, в том числе и чтение папок из списка в файле

RealDT 21-12-2018 14:53 2847377

Код проверял в двух вариантах:
- на небольших файлах, которых много (код отлично справился за неск секунд) и
- на файлах > 1.5 ГБ - robocopy их начинает копировать, на экране светится прогресс копирования, после некоторого ожидания на середине одного из файлов - прервал работу кода...

megaloman 21-12-2018 18:03 2847428

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

@Echo Off
cls
        Set "Disk=%~d0"
        Set "List=%Disk%\dir.txt"
        Set "Backup=%Disk%\%Date:~6,4%-%Date:~3,2%-%Date:~0,2% reserv"

        For /f "usebackq delims=" %%D in ("%List%") Do (
                For /F "usebackq delims=" %%F In (`Dir "%Disk%\%%D\" /B /S /A:D 2^>nul^|Sort /R`) Do (
                        Call :MyMove "%%~dpD" "%Backup%\" "%%F"
                )
                Call :MyMove "%%~dpD" "%Backup%\" "%Disk%\%%D"
        )
pause
GoTo :Eof

:MyMove
        If Not Exist %3 Exit /B 1
        Set "Out=%~3"
        Call Set "Out=%%Out:%~1=%~2%%"
        If Not Exist "%Out%" Md "%Out%"
        2>nul Move /Y "%~3\*.*" "%Out%\"
        Rd %3
GoTo :Eof


RealDT 27-12-2018 12:44 2848554

Спасибо за варианты решения.
Вот ещё один вариант решения:

Код:

@echo off
set curdisk=%~d0
 
Set folder_where=%curdisk%\%date:~6,4%-%date:~3,2%-%date:~0,2% reserv
 
if not exist "%folder_where%" md "%folder_where%"
 
FOR /F "tokens=1,2* delims=;" %%I IN (dir.txt) DO (
    if not exist "%folder_where%\%%J" md "%folder_where%\%%J"
    move /Y "%curdisk%\%%I" "%folder_where%\%%J"
)

При этом структура файла dir.txt поменялась и должна быть такой:
Каталог1\!Папка11\!Папка111\Папка1111;Каталог1\!Папка11\!Папка111
Каталог1\!Папка12\!Папка121\Папка1121;Каталог1\!Папка12\!Папка121
Каталог2\Папка12\Папка!331;Каталог2\Папка12
Каталог3\Папка13\;Каталог3

Т.е.:
- в переменную %%I записывается каталог "что переносить";
- в переменную %%J записывается часть каталога "куда переносить", полный путь "куда переносить" будет таким %folder_where%\%%J

Отличия от начального варианта решения:
- убрал SETLOCAL enabledelayedexpansion, который удалял воскличательные знаки в именах каталогов и файлах;
- убрал внешний цикл FOR (оставил только один цикл);
- добавил неявную переменную %%J
- изменил структуру dir.txt, в котором каждая строка формирует значения для %%I и %%J.

Iska 27-12-2018 17:04 2848610

RealDT, только имейте в виду, что curdisk — не текущий диск, а диск, на котором находится пакетный файл.


Время: 08:43.

Время: 08:43.
© OSzone.net 2001-