2013-04-14 12 views
2

Я очень плохо разбираюсь в пакетных файлах/сценариях, особенно по сравнению с теми, кто «свободно» с ним :). Мне бы очень хотелось помочь создать простой (и легко настраиваемый) пакетный файл/скрипт, который мог бы помочь мне сделать то, что мне нужно сделать (описано ниже).Написание пакетного сценария/файла для преобразования структуры между двумя папками/файлами

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

Моя нынешняя структура является следующим -

PhotosCollection01\ 
|-> Img003.jpg 
|-> Img004.jpg 
|-> Img005.jpg 
|-> Img007.jpg 
|-> Img010.jpg 
|-> ... 
|-> Chosen\ 
    |-> Img005.jpg 
    |-> Img010.jpg 

Пакетный файл/скрипт должен изменить структуру этого -

PhotosCollection01\ 
|-> NewName001.jpg (formerly Img003.jpg) 
|-> NewName002.jpg (formerly Img004.jpg) 
|-> NewName004.jpg (formerly Img007.jpg) 
|-> ... 
|-> Chosen\ 
    |-> NewName003.jpg (formerly Img005.jpg) 
    |-> NewName005.jpg (formerly Img010.jpg) 

Это то, что командный файл/скрипт сделал -

1) Names are all "NewName???.jpg" (from 001 and up) 
2) No duplication of photos under the "Photos" directory and its sub-dirs 
3) The "Chosen" directory holds the same amount of photos as before (these were removed from the "Photos" directory) 
4) The numbering order of the "NewName" photos is kept in the same order as the "Img" order (although numbering is reset to start from 000) 
5) I would love to be able to have "PhotosCollectionXX", "NewNameXXX" and "Chosen" to be able to consist of spaces in their real names 

До (если) я получаю ответ, я буду пытаться учиться и писать сценарий сам. Любая помощь будет очень оценена!

Большое спасибо заранее, Эяль

+0

Я не верю, что существует разумный способ достижения 4) с использованием пакетных файлов. Для этого вам нужен настоящий язык программирования. Если вы хотите оставаться рядом со сценарием, рассмотрите PowerShell или VBScript/JScript. –

ответ

0

Вы могли бы добиться этого без скриптов, если у вас есть Total Commander под Windows (с вашего разделителей пути в примере, я предполагаю, что вы используете Windows). Если вы нажмете Ctrl + B, в нем перечислены все файлы в текущем каталоге и все подкаталоги в одном списке. Затем, если вы выберете все из них (*) и нажмите Ctrl + M, появится инструмент переименования партии, и вы можете переименовать все из них, установить для замены Img с помощью NewName и добавить счетчик в конец имени файла.

1
@ECHO OFF 
SETLOCAL 
SET "relroot=u:\photos collection 01" 
SET "oldmask=im age" 
SET "newmask=new name" 
SET "ext=jpg" 
SET "skipped=" 
:: 
:: step 1 - ensure no 'newname*.ext' exists in the subtree 
:: 
FOR /f %%i IN (
    'DIR /s/b/a-d "%relroot%\%newmask%*.%ext%" 2^>nul^|FIND /c /v "" ' 
) DO IF NOT %%i==0 ECHO Files matching new mask already exist&GOTO :EOF 
:: 
:: step 2 - list target files 
:: 
:temploop 
SET tempfile=%temp%\Photo%random% 
IF EXIST "%tempfile%*" GOTO temploop 
:: now have random tempfile name 
(
FOR /f "delims=" %%i IN (
    'DIR /s/b/a-d "%relroot%\%oldmask%*.%ext%" ' 
) DO (
    ECHO %%~ni*%%~fi 
) 
)>"%tempfile%1" 
:: 
:: Now do the rename 
:: 
SET count=1000 
SET prev=%newmask% 
FOR /f %%i IN ('find /c "*" ^<"%tempfile%1"') DO IF %%i gtr 1000 ECHO %%i files - exceeds capacity&GOTO :eof 
FOR /f "delims=*" %%i IN ('SORT "%tempfile%1"') DO (CALL :incren "%%i") 
IF DEFINED skipped ECHO some files were NOT renamed&DIR /s/b/a-d "%relroot%\%oldmask%*.%ext%" 

DEL "%tempfile%1" 
GOTO :eof 

:incren 
:: repeat? 
IF "%prev%"==%1 GOTO :EOF 
:: no - process next name found 
SET "prev=%~1" 
FOR %%n IN (firstname secondname) DO (SET %%n=) 
:: scan the tempfile, looking for matches to name found 
FOR /f "usebackqtokens=1,2delims=*" %%m IN ("%tempfile%1") DO IF /i "%%m"=="%prev%" (
IF DEFINED firstname SET skipped=Y&IF NOT DEFINED secondname SET secondname=%%n 
IF NOT DEFINED firstname SET firstname=%%n 
) 
IF DEFINED secondname SET firstname=%secondname% 
ECHO REN "%firstname%" "%newmask%%count:~-3%.%ext%" 
SET /a count+=1 
GOTO :eof 

Ну, не слишком сложно в конце концов.

Не совсем ушел с вашей спецификацией - я избегаю удаления файлов, поэтому я не переименовал цели с дублированными именами.

ПУТЕМ слишком много внимания уделяется попытке обработки глупых имен файлов ИМО. Если вы используете в своих именах символы, такие как !%^)=, - ну, вы так умны - вы это понимаете.

Итак, при условии разумного имени и символов имени файла, чтобы работать!

Сначала настройте свой relative root (начальный подкаталог) имя, используемые файлы, старые и новые, а также расширение. Я использую синтаксис set "var=string", чтобы избежать применения блуждающих терминальных пространств, которые невидимы и могут вызвать хаос. Обратите также внимание на то, что в присвоении строк пробелы по обе стороны от «=» значительны.

Первый шаг такой же документированный. Не уверен, что делать, если в дереве есть файлы, соответствующие новому имени, поэтому ничего не делайте. считая строки, которые появляются из dir /s/b/a-d (каталог, с подкаталогами, базовая форма (так что без заголовков) и без имен каталогов) должно быть около 0, если все хорошо.

Мне нравится настраивать tempfiles, используя метод showm. Если в %temp% нет имен, соответствующих выбранному случайному имени, тогда должно быть безопасно использовать это имя + любое приложение, которое вам нравится (так что вы можете создать много tempfiles, если это необходимо.)

Следующий шаг - получить подкаталог старых файлов в базовой форме снова, но на этот раз вывести файл tempfile. То, что выводится, является строкой для каждого файла, только структурированной как часть NAME (%%~ni) звездочкой и полным именем файла (%%~fi). Звездочка действует как разделитель столбцов и безопасна, потому что * не может встречаться в имени файла.

Следующая фаза переименования. Мы начинаем COUNT на 1000, чтобы мы могли использовать последние 3 символа для создания имени. Вы хотите начать с 001, просто используйте 1001 вместо этого. PREV инициализируется значением, которое не может отображаться как имя файла, которое будет переименовано.

Снова подсчитайте имена, которые нужно переименовать. Если слишком много, бросьте корабль.

Следующим шагом является сортировка временного файла, поэтому результат будет обработан в порядке исходного базового имени файла (до «*» в каждой строке), а затем, если имя соответствует, в алфавитном порядке имени подкаталога (так как имя * родитель будет сортировать до имени * parent \ subdir). Каждое обнаруженное NAME затем передается в подпрограмму :incren - цитируется для соответствия требованию пробелов в именах файлов.

Первое, что делает процедура INCREN, это проверить, повторяется ли имя предыдущего имени. Если это так, имя игнорируется (поскольку оно уже обработано). PREV затем устанавливается на следующее имя. SET "prev=%~1" удаляет цитату из первого параметра, а затем присваивает результат prev и вмещающие кавычки предотвращения паразитного пространства от тычка в. firstname и secondname затем устанавливаются на [ничего]

Затем мы сканируем временный файл снова ищу совпадающее имя в качестве первого токена и присвоение второго токена (полное имя файла) до %%n

Когда первое найдено, первое имя не задано, поэтому установите его в полное имя файла. Если второе имя найдено, то firstname уже будет установлен, поэтому установите SKIPPED, чтобы указать, что проблема была обнаружена. Если второе имя файла еще не установлено, то установите secondname на , что full-filename Если будут найдены дополнительные совпадения, то после того, как secondname теперь установлен, ничего дальше делать не будет.

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

Теперь сделайте RENAME. Я только ECHO отредактировал его, но чтобы активировать, удалите ECHO с линии ECHO REN.... Мы знаем, что firstname содержит полное имя файла, который нужно переименовать, и мы знаем, что структурой нового имени файла будет новая маска + последние 3 символа COUNT + точка + выбранное расширение.

и поднять счет для следующего переименования ...

Вот тестовый прогон с ECHO удалены:

============= before ========= 

u:\photos collection 01\im age 612.jpg 
u:\photos collection 01\im age 003.jpg 
u:\photos collection 01\im age 005.jpg 
u:\photos collection 01\im age 610.jpg 
u:\photos collection 01\im age 009.jpg 
u:\photos collection 01\im age 609.jpg 
u:\photos collection 01\im age 505.jpg 
u:\photos collection 01\selection 01\im age 001.jpg 
u:\photos collection 01\selection 01\im age 004.jpg 
u:\photos collection 01\selection 01\im age 005.jpg 
u:\photos collection 01\selection 01\im age 006.jpg 

============= run ========= 

some files were NOT renamed 
u:\photos collection 01\im age 005.jpg 

============= after ========= 

u:\photos collection 01\new name009.jpg 
u:\photos collection 01\new name001.jpg 
u:\photos collection 01\im age 005.jpg 
u:\photos collection 01\new name008.jpg 
u:\photos collection 01\new name005.jpg 
u:\photos collection 01\new name007.jpg 
u:\photos collection 01\new name006.jpg 
u:\photos collection 01\selection 01\new name000.jpg 
u:\photos collection 01\selection 01\new name002.jpg 
u:\photos collection 01\selection 01\new name003.jpg 
u:\photos collection 01\selection 01\new name004.jpg 

ПримечаниеЭтот был выполнен Agains диск FAT, поэтому последовательность реальных файлов одинакова в обоих списках.

0

Попробуйте и удалить echo перед тем move, если выход OK:

@echo off&setlocal 
set "sourcefolder=PhotosCollection01" 

for /r "%sourcefolder%" %%i in (*.jpg) do (
    if defined "$n%%~nxi" set "$d%%~nxi=%%~nxi" 
    set "$p%%~nxi=%%~dpi" 
    set "$n%%~nxi=%%~nxi" 
) 
set "$d" >nul 2>&1 && (
    echo(Duplicate filename(s^): 
    for /f "tokens=2delims==" %%i in ('set $d') do echo(%%i 
    goto:eof 
) 
set /a counter=1000 
for /f "tokens=2delims==" %%i in ('set $n') do (
    set /a counter+=1 
    setlocal enabledelayedexpansion 
    if exist "!$p%%~i!NewName!counter:~-3!%%~xi" (
    echo(file already exists: "!$p%%~i!NewName!counter:~-3!%%~xi" 
    ) else echo move "!$p%%~i!%%~i" "!$p%%~i!NewName!counter:~-3!%%~xi" 
    endlocal 
) 

Сценарий завершается, если повторяющиеся имена файлов находятся во вложенных папках. Если целевой файл уже существует, он не будет перезаписан. Обратите внимание: все папки в% sourcefolder% используют один и тот же счетчик. Если у вас разные варианты, вызовите этот скрипт для каждого или напишите комментарий.

0

Интересная тема! Я понимаю ваш запрос таким образом: 1- Создайте список уникальных имен файлов из PhotosCollection и Chosen, но отдайте приоритет файлам Chosen (файлы PhotosCollection с тем же именем будут удалены). 2- Переименуйте файлы в списке с последовательными номерами, начиная с 001. Пакетный файл ниже достигает этого процесса, но обрабатывает все каталоги в текущем каталоге (от PhotosCollection01 до PhotosCollectionNN) и обрабатывает этот путь все поддиректории под каждым каталог, то есть, если в подкаталоге Chosen есть «братья», все они обрабатываются одинаково.

@echo off 
setlocal 

rem Set this value as you wish (ie: set NewName=New Name With Spaces) 
set NewName=NewName 

rem Process all directories at this level 
for /D %%a in (*) do (
    rem Enter into this directory (ie: PhotosCollection01) 
    cd "%%a" 
    rem Insert file names in the initial list as "parent" (ie: Img003.jpg Img004.jpg Img005.jpg) 
    setlocal EnableDelayedExpansion 
    for %%c in (*.jpg) do (
     set unique[%%c]=. 
    ) 
    rem Process each subdirectory 
    for /D %%b in (*) do (
     rem Enter into this subdirectory (ie: Chosen) 
     cd "%%b" 
     rem Process "nested" file names (ie: Img005.jpg Img010.jpg) 
     for %%c in (*.jpg) do (
     if "!unique[%%c]!" equ "." (
      rem Delete duplicated file in parent directory (ie: PhotosCollection01\Img005.jpg) 
      del "..\%%c" 
     ) 
     rem Insert file name in the list as "nested" 
     set unique[%%c]=%%b 
    ) 
     rem Go back to parent directory (ie: PhotosCollection01) 
     cd .. 
    ) 
    rem Rename all names in the list from 001 and up 
    set number=1000 
    for /F "tokens=2,3 delims=[]=" %%c in ('set unique[') do (
     set /A number+=1 
     ren "%%d\%%c" "%NewName%!number:~-3!.jpg" 
    ) 
    rem Delete the list 
    endlocal 
    rem Go back to original directory (where PhotosColection01...NN exist) 
    cd .. 
) 

Поместите этот командный файл в той же папке, которые содержат коллекции и выполнить его, вы должны сделать это с помощью тестовых файлов несколько раз, пока вы не будете удовлетворены результатом. Обратите внимание, что этот метод может быть легко изменен, чтобы также удалять или переименовывать дублированные файлы во всех папках братьев избранных, то есть если папка «Chosen2» имеет файл Img010.jpg (который также находится в «Избранном»), удалите или переименуйте Chosen's или Chosen2's один (в настоящее время они сохранены, но не переименованы). Все имена каталогов и файлов могут иметь пробелы, но имена, содержащие восклицательные знаки, будут неправильно обработаны; эта деталь может быть исправлена, если это необходимо.

C:\Users\Antonio\Documents\test 
>dir /b 
PhotosCollection01 
renumber.bat 

C:\Users\Antonio\Documents\test 
>dir /b PhotosCollection01 
Chosen 
Img003.jpg 
Img004.jpg 
Img005.jpg 
Img007.jpg 
Img010.jpg 

C:\Users\Antonio\Documents\test 
>dir /b PhotosCollection01\Chosen 
Img005.jpg 
Img010.jpg 

C:\Users\Antonio\Documents\test 
>renumber.bat 

C:\Users\Antonio\Documents\test 
>dir /b PhotosCollection01 
Chosen 
NewName001.jpg 
NewName002.jpg 
NewName004.jpg 

C:\Users\Antonio\Documents\test 
>dir /b PhotosCollection01\Chosen 
NewName003.jpg 
NewName005.jpg