2013-04-14 58 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 
相關問題