批处理脚本可根据文件夹名称重命名子文件夹中的文件

时间:2018-07-16 09:10:30

标签: batch-file directory rename

接着上一个问题:PowerShell/Batch script to rename each file to include original name + folder name

几个月以来,我具有以下文件夹结构:

2017
 │
 ├─April reports
 │   ├─01-04-2018
 │   │ ├─XYZAPPROVED123.pdf
 │   │ ├─XYZAPPROVED123_V2.pdf
 │   │ └─XYZUNAPPROVED123.pdf
 │   │
 │   ├─02-04-2018
 │   │ ├─XYZAPPROVED123.pdf
 │   │ └─XYZUNAPPROVED123.pdf
 │   │
 │   │
 │   └─30-04-2018
 │     ├─XYZAPPROVED123.pdf
 │     └─XYZUNAPPROVED123.pdf
 │ 
 ├─ May reports
 │   ├─01-04-2018
 │   │ ├─XYZAPPROVED123.pdf
 │   │ ├─XYZAPPROVED123_V2.pdf
 │   │ └─XYZUNAPPROVED123.pdf
 │   │
 │   ├─02-04-2018
 │   │ ├─XYZAPPROVED123.pdf
 │   │ └─XYZUNAPPROVED123.pdf
 │   │
 │   │
 │   ├─30-04-2018
 │      ├─XYZAPPROVED123.pdf
 .
 .
 .
 ├─December reports (etc)

一个月中每一天的每个文件夹都包含一个具有相同名称(“ XYZAPPROVED123”或“ XYZUNAPPROVED123”)的批准和未批准的报告。有些包含V2。

我想重命名每个名称,以便删除“ 123”,并将文件夹名称(日期)包含在文件名中,例如“ XYZAPPROVED_01-04-2018”。我不想将文件名完全替换为文件夹的名称,我只想在可能的情况下将其添加在末尾,并用下划线分隔。

完成此操作后,我想删除名称中包含“ XYZUNAPPROVED”的所有文件,并删除同一文件夹中存在“ XYZAPPROVED_V2”的所有“ XYZAPPROVED”文件(版本2取代了原始)。

我已成功使用以下脚本获取了一个批处理脚本,可用于一个月(4月)的报告。我遇到的问题是添加了一个附加循环,以便我可以在所有月份中运行它。

4月脚本(有效):

@echo off
cd "<actual path>"
for /D %%I in ("<actual path>\????-??-??") do (
    for %%J in ("%%I\XYZ*.pdf") do (
        if exist "%%I\XYZUN*" del /F "%%I\XYZUN*.pdf"
        if exist "%%I\%%~nJ_V*.pdf" ( del "%%J" ) else ren "%%J" 
"%%~nJ_%%~nI.pdf"
    )
)

所有月份的脚本-(运行时什么都没发生)

@echo off
cd "<actual path>"
 for /D %%H in ("<actual path>") do (
 rem Enter into the month name folder
  rem process each date
  for /D %%I in ("%%H\????-??-??") do (

      for %%J in ("%%I\XYZ*.pdf") do (
      if exist "%%I\XYZUN*" del /F "%%I\XYZUN*.pdf"
      if exist "%%I\%%~nJ_V*.pdf" ( del "%%J" ) else ren "%%J" "%%~nJ_%%~nI.pdf"

  )

 )
)

我想念什么?

2 个答案:

答案 0 :(得分:2)

这是一种可以实现您想要的解决方案-请参阅所有说明性注释(data Expr = BinaryOperation BinaryOperator Expr Expr | UnaryOperation UnaryOperator Expr | Literal LiteralValue | Variable Id data BinaryOperator = Add | Sub | Mul | Div data UnaryOperator = Not | Negate ):

rem

此脚本从与每天相关的子目录中删除以下文件:

  • 名称中包含@echo off setlocal EnableExtensions DisableDelayedExpansion rem // Define constants here: set "_ROOT=%~dp0TEST" & rem // (path of the root directory) set "_DIR1=????" & rem // (mask for level-1 sub-directories (year)) set "_DIR2=* reports" & rem // (mask for level-2 sub-directories (month)) set "_DIR3=??-??-????" & rem // (mask for level-3 sub-directories (day)) set "_NAMEREN=approved" & rem // (partial name of files to keep) set "_NAMEDEL=unapproved" & rem // (partial name of files to delete) set "_MASKREN=*%_NAMEREN%*" & rem // (name pattern for files to keep) set "_MASKDEL=*%_NAMEDEL%*" & rem // (name pattern for files to delete) set "_FILEEXT=.pdf" & rem // (name extension for all files to process) set "_VERSUFF=V" & rem // (beginning of version suffix in file names) set "_KEEPSUFF=#" & rem // (set non-empty to keep version suffix) rem // Build search string for version suffix: set "SEARCH=_%_VERSUFF%[0123456789][0123456789]*" rem // Walk through all level-1 sub-directories: for /D %%C in ("%_ROOT%\%_DIR1%") do ( rem // Walk through all level-2 sub-directories: for /D %%D in ("%%~C\%_DIR2%") do ( rem // Walk through all level-3 sub-directories: for /D %%E in ("%%~D\%_DIR3%") do ( rem // Loop through all files to delete: for %%F in ("%%~E\%_MASKDEL%%_FILEEXT%") do ( rem // Delete current file: del "%%~F" ) rem // Store path and name of current sub-directory: set "LOC=%%~E" & set "SUB=%%~nxE" rem // Loop through cached and sorted list of all files to potentially keep: for /F "delims= eol=|" %%F in (' 2^> nul dir /B /A:-D /O:N "%%~E\%_MASKREN%%_FILEEXT%" ') do ( rem // Store file name and extension: set "VER=" & set "FILE=%%~nF" & set "EXT=%%~xF" rem // Check if current file name has got a version suffix: echo(%%~nF| > nul findstr /I /E "%SEARCH%" && ( rem // Version suffix encountered, hence extract it: setlocal EnableDelayedExpansion for %%H in ("!FILE:_=" "!") do ( endlocal set "VER=_%%~H" setlocal EnableDelayedExpansion ) endlocal rem /* Check whether there are other files with same name but with another rem version suffix appended: */ for %%I in ("%%~E\%_MASKREN%_%_VERSUFF%*%_FILEEXT%") do ( rem // Filter for correct version suffix: echo(%%~nI| > nul findstr /I /E "%SEARCH%" && ( rem // Extract version suffix: set "NUM=" & set "TEST=%%~nI" setlocal EnableDelayedExpansion for %%J in ("!TEST:_=" "!") do ( endlocal set "NUM=_%%~J" setlocal EnableDelayedExpansion ) rem /* Check whether the other version suffix is higher (or equal) rem than the one of the current file: if !VER:*_%_VERSUFF%^=! lss !NUM:*_%_VERSUFF%^=! ( rem // Other version suffix is higher, so delete current file: if exist "!LOC!\!FILE!!EXT!" del "!LOC!\!FILE!!EXT!" ) endlocal ) ) ) || ( rem /* No version suffix encountered, hence check if there is a file with rem the same name but with a version suffix appended: */ for %%G in ("%%~E\%%~nF_%_VERSUFF%*%%~xF") do ( rem // Filter for correct version suffix: echo(%%~nG| > nul findstr /I /E "%SEARCH%" && ( rem // Delete current file as there is a newer version: if exist "%%~E\%%~F" del "%%~E\%%~F" ) ) ) rem // Check whether current file has been deleted: if exist "%%~E\%%~F" ( rem // Keep version suffix only if desired: if not defined _KEEPSUFF set "VER=" rem // Extract the partial file name to keep: setlocal EnableDelayedExpansion for /F "delims=| eol=|" %%K in ("_!FILE:%_NAMEREN%=|!") do ( endlocal set "NAME=%%K%_NAMEREN%" setlocal EnableDelayedExpansion ) rem // Rename kept file as desired: ren "!LOC!\!FILE!!EXT!" "!NAME:~1!_!SUB!!VER!!EXT!" endlocal ) ) ) ) ) endlocal exit /B 的所有*.pdf文件;
  • 名称中带有unapproved的{​​{1}}文件,但没有版本后缀*.pdf,以防其他approved文件带有_V但附加了版本后缀;
  • 名称中带有*.pdf且版本后缀为approved的{​​{1}}个文件,其后缀的版本号不是遇到的最大版本号;

该脚本会在与每日相关的子目录中保留并重命名以下文件:

  • 名称为*.pdf且版本后缀为approved的{​​{1}}文件,其附加版本号是遇到的最大版本号;保留_V之前的部分,之后的部分由*.pdf加上父目录名称替换;版本后缀可以选择保留(请参见常量approved);

答案 1 :(得分:1)

这是this answer中最后一个批处理文件,由于新要求在批处理文件顶部定义的每个文件名的开头都带有固定前缀而被重写。

@echo off
setlocal EnableExtensions DisableDelayedExpansion
set "Prefix=XYZ"
for /F "delims=" %%I in ('dir "%~dp0%Prefix%Approved*.pdf" /A-D-H /B /S 2^>nul') do call :ProcessFile "%%I"
endlocal
rem Avoid a fall through to the subroutine.
goto :EOF

rem The subroutine ProcessFile first assigns full qualified file name
rem of found approved PDF file to environment variable FullFileName.
rem All occurrences of defined prefix after a backslash are substituted
rem by backslash, defined prefix and additionally the two characters UN.
rem A PDF file with that name in same directory as the found approved PDF
rem is deleted if existing which means there is still an unapproved PDF
rem file for an already approved PDF file.

rem Next the subroutine checks if there is one more approved PDF file
rem starting with same name, but there is additionally _V and any other
rem string in which case the approved PDF file without _V* in name is
rem deleted and subroutine is exited.

rem Otherwise the subroutine assigns path of passed file name ending with
rem a backslash to environment variable FilePath. Next the backslash is
rem removed from file path. Then is checked if the file path ends with
rem folder name "dayreports" in which case also this folder is removed
rem from file path. The file path is processed by command FOR to get
rem the string after last backslash referenced with %%~nxJ which is the
rem name of the folder of which name should be in new file name. Before
rem moving the file with new name containing the date, it is checked if
rem the current file name ends already with an underscore and the name
rem of the folder which should be the date. The subroutine is exited
rem if this condition is true to avoid double processing an already
rem processed file in a previous execution of this batch file.

:ProcessFile
setlocal EnableDelayedExpansion
set "FullFileName=%~1"
set "UnapprovedFile=!FullFileName:\%Prefix%=\%Prefix%Un!"
if exist "%UnapprovedFile%" del /F "%UnapprovedFile%"
endlocal

if exist "%~dp1\%~n1_V*%~x1" (
    del /F %1
    goto :EOF
)

set "FilePath=%~dp1"
set "FilePath=%FilePath:~0,-1%"
if /I "%FilePath:~-11%" == "\dayreports" set "FilePath=%FilePath:~0,-11%"
for %%J in ("%FilePath%") do set "FolderName=%%~nxJ"
set "FileName=%~n1"
if "%FileName:~-11%" == "_%FolderName%" goto :EOF
move /Y %1 "%FilePath%\%~n1_%FolderName%%~x1" >nul
goto :EOF

有一个非常简单的方法可以删除目录树所有目录中的所有*unapproved*.pdf文件,而与同一个目录中存在*approved*.pdf文件无关:

del /A /F /Q /S "%~dp0*unapproved*.pdf"

带有已使用参数的命令 DEL 删除

  • 由于/Q而安静
  • 由于*unapproved*.pdf而导致批处理文件及其所有子目录中的所有/S
  • 由于*unapproved*.pdf而将/F设置为只读属性
  • 包括*unapproved*.pdf在内的/A由于setlocal而设置了隐藏属性。

可以先在批处理文件顶部的 FOR 之前使用此命令行来删除子例程endlocal中的ProcessFile ... *unapproved*.pdf块循环,可以更快地执行批处理文件。

我不建议删除所有*approved*.pdf而不检查同一目录中是否有相应的#createBtn