首页 > 解决方案 > 将 .txt 文件重命名为文件中的第一行并将“()”添加到重复项

问题描述

我正在尝试.txt使用其内容的第一行重命名目录中的 200 多个文件。这些文件包含格式的 IP 地址,例如12.345.678.90. 我找到了一个,它完全可以做到这一点,只是重复项根本没有被重命名。

我已经编辑(根据我的需要),并在 Server2016 和 Windows10 上测试了以下脚本,它重命名了文件,但对重复文件没有任何作用。

@echo off
setlocal EnableDelayedExpansion

rem Multi-thread file rename program
if "%1" equ "Thread" goto ProcessBlock

rem Create the list of file names and count they
cd C:\Renamed_Files
set numFiles=0
(for %%f in (*.txt) do (
        echo %%f
        set /A numFiles+=1
)) > fileNames.tmp

rem Get number of threads and size of each block
set numThreads=%1
if not defined numThreads (
    set /A numThreads=1, blockSize=numFiles
) else (
    set /A blockSize=numFiles/numThreads
)

rem Create asynchronous threads to process block number 2 up to numThreads
if exist thread.* del thread.*
for /L %%t in (2,1,%numThreads%) do (
    echo %time% > thread.%%t
    start "" /B "%~F0" Thread %%t
)

rem Process block number 1
set count=0
for /F "delims=" %%f in (fileNames.tmp) do (
    set /p line1=<%%f
    ren "%%f" "!line1:~0,40!.txt"
    set /A count+=1
    if !count! equ %blockSize% goto endFirstBlock
)

:endFirstBlock

rem Wait for all asynchronous threads to end
if exist thread.* goto endFirstBlock

rem Delete the auxiliary file and end
del fileNames.tmp
goto :EOF


rem Process blocks 2 and up (asynchronous thread)

:ProcessBlock 
set /A skip=(%2-1)*blockSize, count=0
for /F "skip=%skip% delims=" %%f in (fileNames.tmp) do (
    set /p line1=<%%f
    ren "%%f" "!line1:~0,40!.txt"
    set /A count+=1
    if !count! equ %blockSize% goto endBlock
)
:endBlock
del thread.%2
exit

我希望重命名.txt文件并添加()一些重复项,以便仍然可以使用相同的批处理文件重命名重复项(当然是通过编辑),还是需要新的批处理?有什么建议吗?或欢迎新代码。

最终,重复的文件可以合并为一个(因为它们无论如何都会包含相同的 IP 地址),然后将文件重命名为它们的第一行内容。

标签: batch-file

解决方案


对于多个线程,您可能会遇到导致冲突的竞争条件。我开始的方式是使用线程号来避免冲突。我正在展示未经测试的示例代码。由于 DOS 中括号的困难,我将改为使用句点并向您推荐相同的内容:

...

:ProcessBlock 
set /A skip=(%2-1)*blockSize, count=0
for /F "skip=%skip% delims=" %%f in (fileNames.tmp) do call :ProcessBlockLoop "%%~f" %2
goto :eof

:ProcessBlockLoop
set /p line1=<"%~1"
set "filename=!line1:~0,40!"

:: Check for an existing file.
if not exist "%filename%.txt" goto :ProcessBlockLoopContinue

:: if we get here then there is an existing file.
set DupCnt=1

:ProcessBlockFilenameLoop

if not exist "%filename%.%2.%DupCnt%.txt" (
   set filename=%filename%.%2.%DupCnt%
   goto :ProcessBlockLoopContinue
)
:: increment our duplicate counter and try again
set /a DupCnt += 1
goto :ProcessBlockFilenameLoop


:ProcessBlockLoopContinue
:: Try the rename.  If the rename fails, then reset the variables and loop again.
:: A retry counter should be added to avoid an infinite loop.
ren "%%f" "%filename%.txt" || set DupCnt=1&&set "filename=!line1:~0,40!"&&goto :ProcessBlockFilenameLoop

:: If we're here, the rename should have worked.  You could double check again if desired.
set /A count+=1
if %count% equ %blockSize% (
   del thread.%2
   exit
)
goto :eof

推荐阅读