Я новичок в пакетных файлах и DOS, но я надеюсь, что вы все равно сможете мне помочь.

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

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

2 ответа2

1

На основе связанного примера я расширил код, чтобы имя файла было изменено на возрастающее число, чтобы все XML-файлы копировались в X:\destination, используя старое имя файла (вставленное %%~nxf), плюс увеличивающееся число.

@Echo Off
SET /A counter=1
for /R "X:\source" %%f in (*.xml) do (
    copy "%%f" "X:\destination\%%~nxf_!counter!.xml"
    SET /A counter=!counter!+1
    echo !counter!
)

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

Поэтому, если вы сохраните скрипт выше как mycopy.cmd, вы можете запустить его следующим образом:

cmd.exe /v:on /c "mycopy.cmd"
1

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

@ECHO OFF

SETLOCAL EnableDelayedExpansion

SET _destination=%~1
SHIFT

SET _source=%~1
SHIFT

SET _cmdstring=dir /b /s

:LoopGetExt
    SET _cmdstring=%_cmdstring% "%_source%\*%~1"
    SHIFT
    IF NOT "%~1"=="" GOTO LoopGetExt
::End LoopGetExt

FOR /F "tokens=*" %%i IN ('%_cmdstring%') DO (
        SET _fullpath=%%i
        SET _splitpath=!_fullpath:\=^

!
        SET _filename=%%~ni%%~xi
        FOR /F "tokens=*" %%j IN ("!_splitpath!") DO (
            IF NOT "%%j"=="!_filename!" SET _dirname=%%j
        )

        ECHO "%%i" =^> "%_destination%\!_dirname!_!_filename!"
        COPY "%%i" "%_destination%\!_dirname!_!_filename!"
)

ENDLOCAL

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

copyfiles.bat <destination> <source> <ext> [ext]

например

copyfiles.bat "C:\Dest" "C:\Source" .txt .xml .csv .log

РЕДАКТИРОВАТЬ (согласно запросу в первом комментарии)

::copyfiles.bat <destination> <source> <ext> [ext]
::e.g.
::copyfiles.bat "C:\Dest" "C:\Source" .txt .xml .csv .log

@ECHO OFF

SETLOCAL EnableDelayedExpansion

SET _destination=%~1
SHIFT

SET _source=%~1
SHIFT

SET _cmdstring=dir /b /s

:LoopGetExt
    SET _cmdstring=%_cmdstring% "%_source%\*%~1"
    SHIFT
    IF NOT "%~1"=="" GOTO LoopGetExt
::End LoopGetExt

FOR /F "tokens=*" %%i IN ('%_cmdstring%') DO (
        SET _fullpath=%%i
        SET _splitpath=!_fullpath:\=^

!
        SET _filename=%%~ni
        FOR /F "tokens=1 delims=. " %%j IN ("!_splitpath!") DO (
            IF NOT "%%j"=="!_filename!" SET _dirname=%%j
        )

        ECHO "%%i" =^> "%_destination%\!_dirname!%%~xi"
        COPY "%%i" "%_destination%\!_dirname!%%~xi"
)

ENDLOCAL

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