Пакетный файл Windows для копирования и хранения дубликатов - PullRequest
5 голосов
/ 09 марта 2011

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

md "My new folder"
for /D %i in (*) do copy "%i\*" ".\My New Folder"

, однако, я также хочу сохранить файлы с дубликатами (например, если для folder1 и folder2 оба имеют изображения с именем 001.jpg, я хочу, чтобы оба были скопированы в новую папку).Мне не важно, какие новые имена файлов!Иметь:

001.jpg
001(1).jpg
001(2).jpg

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

1.jpg
2.jpg
3.jpg
etc

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

Спасибо за вашу помощь!

Ответы [ 3 ]

9 голосов
/ 09 марта 2011

Это должно работать для вас. Он добавляет число после расширения, но вы можете легко переместить его куда угодно. Я скопировал файлы из каталога. \ Src, поскольку, если у вас есть источники на том же уровне, что и пакетный файл, пакетный файл также пытается оценить test_folder. Наилучшим выбором было бы жестко закодировать test_folder, чтобы он где-то не оценивался командой DIR / S / B ...

@echo off
SETLOCAL ENABLEDELAYEDEXPANSION
set TESTFOLDER=test_folder
md "%TESTFOLDER%"

set /a counter=0
FOR /F "tokens=*" %%i IN ('DIR /S /B /A-D .\src\*') DO FOR /F "tokens=*" %%j IN ('DIR /B "%%i"') DO IF EXIST ".\%TESTFOLDER%\%%j" (
        set /a counter=!counter!+1
        echo folder: %TESTFOLDER%
        copy "%%i" ".\%TESTFOLDER%\%%j_!counter!"
    ) ELSE copy "%%i" ".\%TESTFOLDER%\%%j"
:eof
8 голосов
/ 08 декабря 2014

Следующий скрипт - улучшенная версия ответа aflat.

Скрипт ожидает два аргумента: SourcePath TargetPath.

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

Выдает ошибку, если TargetPath уже существует, поскольку, возможно, уже существуют имена с суффиксом _n.

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

Сценарий более надежен, чем афлатный ответ. Например, имена с ! работают просто отлично. Он также реализует алгоритм aflat более прямым и эффективным способом.

::copyFlat sourcePath  TargetPath
@echo off
setlocal disableDelayedExpansion

:: Initialize and validate arguments
if "%~2" equ "" echo Error: Insufficient arguments>&2&exit /b 1
set "source=%~f1"
if not exist "%source%\" echo Error: Source folder "%source%" does not exist>&2&exit /b 1
set "target=%~f2"
if exist "%target%\" echo Error: Target folder "%target%" already exists>&2&exit /b 1

:: Do the work
md "%target%"
set /a n=0
for /r "%source%" %%F in (*) do if "%%~dpF" neq "%target%\" (
  if exist "%target%\%%~nxF" (
    set /a n+=1
    set "full=%%F"
    set "name=%%~nF"
    set "ext=%%~xF"
    setlocal enableDelayedExpansion
    copy "!full!" "!target!\!name!_!n!!ext!" >nul
    endlocal
  ) else copy "%%F" "%target%" >nul
)
0 голосов
/ 18 октября 2015

Или вы можете установить git bash (https://git -for-windows.github.io / ) и запустить следующее:

mv --backup=numbered src\*.* destinationFolder

Это создаст файлы, которые выглядят какfilename.ext. ~ 1 ~, filename.ext. ~ 2 ~ ... Это может быть достаточно для вас, в моем случае мне не понравилось потерять исходное расширение файла, поэтому вы можете переименовать его, запустив нижеприведенное в пункте назначенияпапка:

ls *~ | sed 's/\(.*\)\.\(.*\)\.~\(.*\)~/mv -i & \1.\3.\2/'

Это напечатает команды переименования следующим образом: mv filename.ext. ~ 1 ~ filename.1.ext

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

  ls *~ | sed 's/\(.*\)\.\(.*\)\.~\(.*\)~/mv -i & \1.\3.\2/' | sh

Адаптировано из этого ответа (https://stackoverflow.com/a/2372739)

...