2013-04-14 31 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 

直到(如果)我得到一个答案,我会努力学习,写剧本我自己。任何帮助将非常感激!

提前许多感谢, 的Eyal

+0

我不相信,有任何理智的方法来实现4)使用批处理文件。为此你需要一些真正的编程语言。如果您想保持接近脚本,请考虑PowerShell或VBScript/JScript。 –

回答

0

您可能能够达到这一点没有脚本,如果您有Windows下的总指挥官(从例如你的路径分隔符,我假设你使用的是Windows)。 如果您按Ctrl + B,它会列出当前目录中的所有文件和一个列表中的所有子目录。然后,如果选择全部(*),然后按Ctrl + M,则批量重命名工具将出现,您可以重命名所有这些文件,设置为用NewName替换Img,并在文件名的末尾添加一个计数器。

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 

好吧,毕竟不是太难。

不太符合你的规范 - 我不想删除文件,所以我mereley没有重命名重名的任何目标。

试图处理愚蠢的文件名海事组织过于关注。如果你在你的文件名中使用了!%^)=这样的字符 - 那么你非常聪明 - 你会发现它。

因此,假设合理的文件名字符和空格,工作!

首先设置您的relative root(起始子目录)名称,要使用的文件掩码,旧的和新的以及扩展名。我使用set "var=string"语法来避免应用杂乱的终端空间,这些空间是不可见的并且可能导致混乱。还要注意,在一个字符串赋值中,'='两边的空格是重要的。

第一步是记录。如果在树中已经有与新名称匹配的文件,不知道该怎么做 - 所以不要做任何事情。从dir /s/b/a-d(包含子目录,基本表单(因此不包含标题)和目录名称)目录中出现的行数应该为0,如果一切正常。

我喜欢用showm方法设置tempfiles。如果%temp%中没有与选择的随机名匹配的名称,那么使用该名称+您喜欢的任何附录应该是安全的(如果需要,可以创建许多临时文件)。

下一步是获取子目录再次使用基本形式的旧名称文件 - 但是这次输出到tempfile。什么是输出是每个文件的一行,只有名称部分(%%~ni)以星号和完整文件名(%%~fi)结构。星号充当列分隔符并且安全,因为*不能出现在文件名中。

接下来是重命名阶段。我们在1000处开始COUNT,以便我们可以使用最后3个字符来创建名称。你想从001开始,只需要使用1001。 PREV被初始化为一个不能显示为要重命名的文件名的值。

再次,计算要重命名的名称。如果太多,放弃船舶。

下一步是对tempfile进行排序,因此结果将按照原始base-filename(在每行中的“*”之前)进行处理,然后如果名称匹配,按照子目录名称的字母顺序(因为name * parent会在name * parent \ subdir之前排序)。遇到的每个名称然后传递到:incren例程 - 引用以适应文件名空间要求。

INCREN例程所做的第一件事是检查名称是否重复遇到的以前的名称。如果是这样,名称将被忽略(因为它已经被处理)。然后将PREV设置为遇到的下一个名称。 SET "prev=%~1"去除第一个参数报价,那么结果firstname分配给prev和封闭引号防止杂散空间从碰撞。和secondname,然后设置为[无]

然后,我们再次扫描临时文件,找了匹配名称作为第一个标记并将第二个标记(全文件名)分配给%%n

当第一个找到时,firstname没有设置,因此将其设置为完整文件名。 如果找到第二个名字,则firstname将已设置,因此请设置SKIPPED来标记已遇到问题。如果第二个文件名尚未设置,则将secondname设置为全文件名 应该进一步匹配找到,那么因为现在设置了secondname,所以不会做任何进一步的处理。

处理完文件后,我们将firstname设置为第一个完整文件名(因为相对根是第一个遇到的),并且secondname仅在找到两个或更多匹配名称时才会设置。在这种情况下,将firstname设置为遇到的第二个名称的值,该名称将位于较低的子目录中。

现在做RENAME。我只是ECHO编辑它,但要激活,从ECHO REN...线删除ECHO。我们知道firstname包含要重命名的文件的全名,并且我们知道新文件名的结构将成为新的掩码+ COUNT的最后3个字符+一个点+所选扩展名。

并撞上计数准备下一次重命名...

这是一个测试运行与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

试试这个,move之前删除echo,如果输出是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 .. 
) 

将这个批处理文件中包含集合并执行相同的文件夹,你必须做到这一点与测试文件几次,直到你满意的结果。请注意,该方法可以很容易地修改,以删除或重命名所有Chosen的兄弟文件夹中的重复文件,即如果“Chosen2”文件夹有Img010.jpg文件(也在选中),删除或重命名Chosen的或Chosen2的文件一个(目前它们被保留,但未被重命名)。所有目录和文件名都可能有空格,但包含感叹号的名称将不会被正确处理;如果需要,这个细节可能是固定的。

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 
相关问题