PowerShell /批处理脚本重命名每个文件以包括原始名称+文件夹名称 [英] PowerShell/Batch script to rename each file to include original name + folder name

查看:115
本文介绍了PowerShell /批处理脚本重命名每个文件以包括原始名称+文件夹名称的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我具有以下文件夹结构:

I have the following folder structure:


April reports
├─01-04-2018
│ ├─approved123.pdf
│ ├─approved123_V2.pdf
│ └─unapproved123.pdf
│
├─02-04-2018
│ ├─approved123.pdf
│ └─unapproved123.pdf
╎
╎
└─30-04-2018
  ├─approved123.pdf
  └─unapproved123.pdf

4月的每一天的每个文件夹包含一个具有相同名称( approved123或 unapproved123)的已批准和未批准的报告。

Each folder for each day in April contains an approved and an unapproved report with the same name ("approved123" or "unapproved123"). Some contain a V2.

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

I want to rename each one so that the "123" is removed and the folder name (the date) is included in the filename e.g. "approved_01-04-2018". I don't want to completely replace the filename with the name of the folder, I just want it added on at the end separated by an underscore if possible.

完成此操作后,我想删除名称中包含未批准的所有文件,并删除同一文件夹中有 approved_V2的所有已批准文件(版本2代替原始文件)。

Once I've done that, I'd like to delete all the files that contain "unapproved" in the name and delete any "approved" files where there is an "approved_V2" in the same folder (version 2 supersedes the original).

第一步,我尝试编写一个批处理脚本(编写批处理或Powershell脚本的完整初学者),但是它不起作用,或者多次向每个文件添加文件夹名称:

For the first step I have tried writing a batch script (complete beginner in writing batch or powershell scripts) but it's not working or it's adding the folder name to each file multiple times:

@echo off
From the folder "April Reports"
rem Process each date
for /D %%d in (*) do (
    cd "%%d"
    rem rename all files
    for /d %%a in (*) do for %%b in ("%%~dpa\.") do ren "%%~a" "%%~nxb_%%~nxa"
)


推荐答案

第一个解决方案仅适用于NTFS驱动器,并且希望该批处理文件在包含 4月报告作为子目录的目录中。

The first solution works only on NTFS drives and expects that the batch file is in the directory containing April reports as subdirectory.

@echo off
for /D %%I in ("%~dp0April reports\??-??-????") do (
    for %%J in ("%%I\approved*.pdf") do (
        if exist "%%I\un%%~nxJ" del /F "%%I\un%%~nxJ"
        if exist "%%I\%%~nJ_V*.pdf" ( del "%%J" ) else ren "%%J" "%%~nJ_%%~nI.pdf"
    )
)

在NTFS驱动器上,结果是:

On NTFS drives the result is:


  • 4月报告


    • 2018年1月4日


      • approved123_V2_01-04-2018.pdf


      • 已批准123_02-04-2018.pdf


      • approved123_30-04-2018.pdf

      但是此批处理文件在FAT32或exFAT驱动器上无法正常工作由于文件 4月报告\2018年1月4日provapproved123_V2.pdf 被处理了三遍,最终使名称 approved123_V2_01-04-2018_01-04-2018_01-04-2018。 pdf ,因为文件分配表中的文件条目列表与 approved * .pdf模式匹配。

      But this batch file does not work as expected on FAT32 or exFAT drives because of file April reports\01-04-2018\approved123_V2.pdf is processed three times resulting in having finally the name approved123_V2_01-04-2018_01-04-2018_01-04-2018.pdf because of list of file entries in file allocation table matching the pattern approved*.pdf changes while running the inner loop.

      针对FAT32和exFAT驱动器的解决方案是在内部循环中使用捕获的文件名列表。

      The solution for FAT32 and exFAT drives is using for inner loop a captured list of file names.

      @echo off
      for /D %%I in ("%~dp0April reports\??-??-????") do (
          for /F "delims=" %%J in ('dir "%%I\approved*.pdf" /A-D-H /B 2^>nul') do (
              if exist "%%I\un%%~nxJ" del /F "%%I\un%%~nxJ"
              if exist "%%I\%%~nJ_V*.pdf" ( del /F "%%I\%%J" ) else ren "%%I\%%J" "%%~nJ_%%~nI.pdf"
          )
      )
      

      现在结果与FAT32和exFAT驱动器上的第一个批处理文件相同。

      Now the result is the same as with first batch file also on FAT32 and exFAT drives.

      命令行 dir %% I\approved * .pdf / ADH / B 2> nul FOR 在后台以 cmd / C 开始的单独命令过程中执行。 DIR 仅输出不带路径的文件名,这需要引用 %% I 路径,其中完整的合格文件名(文件路径+文件名+其他命令行上需要)。 DIR 输出的用于处理后台命令过程的 STDOUT 的文件名由 FOR 捕获,然后逐行处理。因此,在运行命令 DEL REN 时文件分配表上的更改不再重要。

      The command line dir "%%I\approved*.pdf" /A-D-H /B 2>nul is executed by FOR in a separate command process started in background with cmd /C. DIR outputs just the file names without path which requires to reference the path with %%I where full qualified file name (file path + file name + file extension) is needed on the other command lines. The file names output by DIR to handle STDOUT of background command process are captured by FOR and then processed line by line. So the changes on file allocation table during running the commands DEL and REN do not matter anymore.

      也请阅读有关使用命令重定向操作符的Microsoft文章,对 2> nul 。重定向操作符> 必须在 FOR 命令行上使用插入符号 ^ 进行转义,以转至Windows命令解释器在执行命令 FOR 之前处理Windows命令行时,将其解释为文字字符,该命令在单独启动的命令进程中执行嵌入式 dir 命令行

      Read also the Microsoft article about Using Command Redirection Operators for an explanation of 2>nul. The redirection operator > must be escaped with caret character ^ on FOR command line to be interpreted as literal character when Windows command interpreter processes this command line before executing command FOR which executes the embedded dir command line in a separate command process started in background.

      但是根据问题,让我们假设目录结构如下将文件上移一个文件夹级别


      • 四月报告


        • 2018年1月4日


          • 日报表


            • approved123.pdf

            • approved123_V2.pdf

            • unapproved123.pdf

            • April reports
              • 01-04-2018
                • dayreports
                  • approved123.pdf
                  • approved123_V2.pdf
                  • unapproved123.pdf

                  • 日间报告


                    • approved123.pdf

                    • unapproved123.pdf


                    • 日间报告


                      • approved123.pdf

                      • unapproved123.pdf

                      通过对第二批处理文件进行小的修改,可以获得相同的结果

                      By making a small modification to second batch file the same result can be achieved as posted above.

                      @echo off
                      for /D %%I in ("%~dp0April reports\??-??-????") do (
                          for /F "delims=" %%J in ('dir "%%I\dayreports\approved*.pdf" /A-D-H /B 2^>nul') do (
                              if exist "%%I\dayreports\un%%~nxJ" del /F "%%I\dayreports\un%%~nxJ"
                              if exist "%%I\dayreports\%%~nJ_V*.pdf" ( del /F "%%I\dayreports\%%J" ) else move /Y "%%I\dayreports\%%J" "%%I\%%~nJ_%%~nI.pdf" >nul
                          )
                          rd "%%I\dayreports" 2>nul 
                      )
                      

                      dayreports 文件路径,并使用命令 MOVE 而不是命令 REN 将带有新文件名的其余文件在文件夹层次结构中上移一层。如果最终为空,则使用命令 RD 删除文件夹 dayreports

                      dayreports is additionally added to file paths and command MOVE is used instead of command REN to move the remaining file up one level in folder hierarchy with new file name. Command RD is used to delete the folder dayreports if being finally empty.

                      此处是另一种变体,它仅处理目录的整个目录树中的所有 approved * .pdf ,该目录树包含独立于文件系统工作的批处理文件,以及使用PDF的两个目录结构目录中带有日期的文件,或目录 dayreports 的子目录中的文件。通过检查要移动/重命名的文件是否已经包含文件夹名称(日期),这样可以避免多次处理 approved * .pdf ,因此可以在整个目录上多次执行

                      Here is one more variant which simply processes all approved*.pdf in entire directory tree of the directory containing the batch file working independent on file system and for both directory structures with either the PDF files in directory with date in directory name or in a subdirectory dayreports. It avoids processing approved*.pdf more than once by checking if a file to move/rename contains already the folder name (date) and so can be executed multiple times on entire directory tree.

                      @echo off
                      setlocal EnableExtensions DisableDelayedExpansion
                      for /F "delims=" %%I in ('dir "%~dp0approved*.pdf" /A-D-H /B /S 2^>nul') do (
                          if exist "%%~dpI\un%%~nxI" del /F "%%~dpI\un%%~nxI"
                          if exist "%%~dpI\%%~nI_V*%%~xI" ( del /F "%%I" ) else call :MoveFile "%%I"
                      )
                      endlocal
                      rem Avoid a fall through to the subroutine.
                      goto :EOF
                      
                      rem The subroutine MoveFile 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.
                      
                      :MoveFile
                      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
                      

                      要了解所使用的命令及其工作方式,请打开命令提示符窗口,在其中执行以下命令,并非常仔细地阅读每个命令显示的所有帮助页面。

                      For understanding the used commands and how they work, open a command prompt window, execute there the following commands, and read entirely all help pages displayed for each command very carefully.


                      • 通话/? ...还解释了%〜dp0 驱动并传递参数0的路径,该参数是批处理文件的完整路径,始终以反斜杠结尾。

                      • del /?

                      • dir /?

                      • echo /?

                      • endlocal /?

                      • 用于/?

                      • 如果/?

                      • 移动/?

                      • rd /?

                      • ren /?

                      • set /?

                      • setlocal /?

                      • call /? ... explains also %~dp0 which expands to drive and path of argument 0 which is the full path of the batch file ending always with a backslash.
                      • del /?
                      • dir /?
                      • echo /?
                      • endlocal /?
                      • for /?
                      • if /?
                      • move /?
                      • rd /?
                      • ren /?
                      • set /?
                      • setlocal /?

                      这篇关于PowerShell /批处理脚本重命名每个文件以包括原始名称+文件夹名称的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆