Пакетный файл для перемещения файлов на один уровень вверх с переименованием дубликатов

Я пытался создать пакетный файл, который я могу просто поместить в каталог MAIN FOLDER, и при его запуске все *.EXT переместятся на один уровень вверх в Folder2 и Folder3 соответственно:

C:\Main Folder\Folder2\Folder3a\File1.EXT
C:\Main Folder\Folder2\Folder3b\File2.EXT
C:\Main Folder\Folder2\Folder3c\File3.EXT
C:\Main Folder\Folder2\Folder3d\File1.EXT
C:\Main Folder\Folder3\Folder3a\File1.EXT
C:\Main Folder\Folder3\Folder3b\File2.EXT
C:\Main Folder\Folder3\Folder3c\File3.EXT
C:\Main Folder\Folder3\Folder3d\File1.EXT

Проблема в том, что есть дубликаты: File1.EXT в подпапках Folder2 и Folder3.
Все, что я нашел здесь для перемещения файлов на один уровень выше, всегда перезаписывает дубликаты.
И решения, которые я нашел для переименования дубликатов не «слились» с решениями для перемещения файлов.

Может ли кто-нибудь предложить более простой способ?


person user2826193    schedule 08.04.2018    source источник
comment
Этот сайт предназначен для того, чтобы помочь вам с вашим кодом, вы не разместили код, и поэтому нам нечем вам помочь. Отредактируйте свой вопрос и включите код пакетного файла, который вы пробовали и с которым у вас возникли проблемы. Если вы не знаете, как что-то сделать, то ваша работа — искать и пробовать, прежде чем обращаться сюда за помощью; Вы можете использовать строку поиска в верхней части этой страницы для поиска ключевых слов. Если вы включите [batch-file] в начале строки поиска, вы сможете сузить результаты до этого конкретного языка сценариев.   -  person Compo    schedule 08.04.2018
comment
Я отсылаю вас к вашему предыдущему, почти идентичному вопросу, и моему ответу на него!   -  person Compo    schedule 08.04.2018
comment
Переименуйте перед перемещением.   -  person SomethingDark    schedule 09.04.2018


Ответы (2)


@echo off
setlocal

if "%~1" == "test" call :test

for /d /r %%F in (*) do (
    for /d %%G in ("%%F\*") do (
        for %%H in ("%%~G\*.EXT") do (
            call :move "%%~H" "%%~F"
        )
    )
)
exit /b

:move
setlocal

if /i not exist "%~2\%~nx1" (
    echo 1. move "%~1" "%~2"
    move "%~1" "%~2"
    exit /b
)

set "name=%~n1"

for /l %%I in (1 1 9) do (
    if "%name:~-4%" == " (%%I)" (
        set "name=%name:~0,-4%"
    )
)

for /l %%I in (1 1 9) do (
    if not exist "%~2\%name% (%%I)%~x1" (
        echo 2. move "%~1" "%~2\%name% (%%I)%~x1"
        move "%~1" "%~2\%name% (%%I)%~x1"
        exit /b
    )
)
exit /b

:test
if exist "Main Folder" rd /s /q "Main Folder"
call :prep "Main Folder\Folder2\Folder3a" "File1.EXT"
call :prep "Main Folder\Folder2\Folder3b" "File2.EXT"
call :prep "Main Folder\Folder2\Folder3c" "File3.EXT"
call :prep "Main Folder\Folder2\Folder3d" "File1.EXT"
call :prep "Main Folder\Folder3\Folder3a" "File1.EXT"
call :prep "Main Folder\Folder3\Folder3b" "File2.EXT"
call :prep "Main Folder\Folder3\Folder3c" "File3.EXT"
call :prep "Main Folder\Folder3\Folder3d" "File1.EXT"
pushd "Main Folder" || exit /b 1
echo Prepared to test.
pause
exit /b

:prep
if /i not exist "%~1" md "%~1"
if /i not exist "%~1\%~2" type nul > "%~1\%~2"
exit /b

Интегрированный тестовый код упрощает тестирование. Удалите тестовый код, если хотите. Протестируйте, используя test в качестве 1-го аргумента, т.е. main.cmd test.

На основе цикла, который вы разместили в Как создать пакетный файл, который перемещает файлы из подпапки вверх на один уровень, переименовывая дубликаты? Цикл дает вам путь к целевому файлу и путь к целевому каталогу.

Метка :move вызывается с каждым циклом цикла, и 1-й определяет, не существует ли целевой файл. Если не существует, делает перемещение и выходит из метки. Если существует, использует другой цикл для обнаружения и обрезает имя файла, если оно заканчивается на (N), где N — число от 1 до 9. Затем он входит в другой цикл для перемещения с именем файла назначения с 1-м доступным (N), добавленным к имени.

Проверено в корне D:\. Вывод, который я получаю:

D:\> main.cmd test
Prepared to test.
Press any key to continue . . .
1. move "D:\Main Folder\Folder2\Folder3a\File1.EXT" "D:\Main Folder\Folder2"
        1 file(s) moved.
1. move "D:\Main Folder\Folder2\Folder3b\File2.EXT" "D:\Main Folder\Folder2"
        1 file(s) moved.
1. move "D:\Main Folder\Folder2\Folder3c\File3.EXT" "D:\Main Folder\Folder2"
        1 file(s) moved.
2. move "D:\Main Folder\Folder2\Folder3d\File1.EXT" "D:\Main Folder\Folder2\File1 (1).EXT"
        1 file(s) moved.
1. move "D:\Main Folder\Folder3\Folder3a\File1.EXT" "D:\Main Folder\Folder3"
        1 file(s) moved.
1. move "D:\Main Folder\Folder3\Folder3b\File2.EXT" "D:\Main Folder\Folder3"
        1 file(s) moved.
1. move "D:\Main Folder\Folder3\Folder3c\File3.EXT" "D:\Main Folder\Folder3"
        1 file(s) moved.
2. move "D:\Main Folder\Folder3\Folder3d\File1.EXT" "D:\Main Folder\Folder3\File1 (1).EXT"
        1 file(s) moved.

Как видно, 2 файла перемещаются с добавлением (1) к имени файла. Это строки, начинающиеся с 2.. Строки, начинающиеся с 1., перемещены с неизмененными именами файлов.

person michael_heath    schedule 09.04.2018

Этот закомментированный пакетный файл можно использовать для этой задачи:

@echo off
setlocal EnableExtensions DisableDelayedExpansion

rem Search for any file two directory levels below specified directory
rem and pass to subroutine MoveFile the name of the file with full path.

for /D %%A in ("C:\Main Folder\*") do (
    for /D %%B in ("%%A\*") do (
       for /F "delims=" %%I in ('dir "%%B\*" /A-D /B /S 2^>nul') do call :MoveFile "%%I"
    )
)

endlocal
goto :EOF

:MoveFile
set "FilePath=%~dp1"
set "FileNameOnly=%~n1"
set "FileNameFull=%~1"
set "FileName+Ext=%~nx1"
set "FileExtension=%~x1"

rem For files staring with a dot and not containing one more dot.
if "%FileNameOnly%" == "" set "FileNameOnly=%~x1" & set "FileExtension="

rem Get path to parent folder ending with a backslash.
for /F "delims=" %%J in ("%FilePath:~0,-1%") do set "FileParent=%%~dpJ"

rem Uncomment the line below to see the values of the six File* variables.
rem set File & echo/

rem Does a file with current file name not exist in parent folder?
if not exist "%FileParent%%FileName+Ext%" (
    rem Move the file to parent folder and if this was successful
    rem delete the folder of the moved file if being empty now.
    move "%FileNameFull%" "%FileParent%%FileName+Ext%" >nul
    if not errorlevel 1 rd "%FilePath%" 2>nul
    goto :EOF
)

set "FileNumber=1"
:NextFile
if exist "%FileParent%%FileNameOnly%_%FileNumber%%FileExtension%" set /A "FileNumber+=1" & goto NextFile

move "%FileNameFull%" "%FileParent%%FileNameOnly%_%FileNumber%%FileExtension%" >nul
if not errorlevel 1 rd "%FilePath%" 2>nul
goto :EOF

Результат для данного примера:

C:\Main Folder\Folder2\File1.EXT
C:\Main Folder\Folder2\File1_1.EXT
C:\Main Folder\Folder2\File2.EXT
C:\Main Folder\Folder2\File3.EXT
C:\Main Folder\Folder3\File1.EXT
C:\Main Folder\Folder3\File1_1.EXT
C:\Main Folder\Folder3\File2.EXT
C:\Main Folder\Folder3\File3.EXT

И запуск батника второй раз ничего не меняет.

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

  • call /?
  • echo /?
  • endlocal /?
  • for /?
  • goto /?
  • if /?
  • move /?
  • rd /?
  • rem /?
  • set /?
  • setlocal /?

Смотрите также:

person Mofi    schedule 09.04.2018