批处理文件循环跳过文件,如果名称包含

Posted

技术标签:

【中文标题】批处理文件循环跳过文件,如果名称包含【英文标题】:Batch File Loop Skip File if name contains 【发布时间】:2013-05-29 05:14:13 【问题描述】:

我正在创建这个与 handbrakecli 配合使用的批处理文件,以将 avi 批量转换为 mp4。

但是我被困在如何继续循环并跳过循环内的当前文件。

FOR /R "%somepath%" %%G in (*.avi) DO (

rem skip if filename contains word trailer

rem skip if file name contains word sample

rem do conversion
)

目前这不适用于跳过包含预告片或示例的文件

我尝试过使用 find 或 findstr 都无法跳过。

    echo "%%G" | c:\windows\system32\findstr /i "trailer" > NUL
    If %ERRORLEVEL% EQU 1 set skip Yes

这里是示例。

    echo "%%G" | c:\windows\system32\findstr /i "sample" > NUL
    If %ERRORLEVEL% EQU 1 set skip Yes

如果文件包含预告片或样本,我不想进行任何 handbrakecli 转换,而只是跳过它。

我会通过 echo 显示哪些文件被转换了,它确实包含名称中带有 Sample 或 sample 的文件。

我尝试过使用 find 或 findstr,但都无法将 skip 设置为 yes

如果跳过 == 不做(rem 做转换)

我只想转换非预告片/示例 avi 文件。

感谢您的宝贵时间。

【问题讨论】:

pastebin.com/qY2u4HX2 这已更新所有当前代码,并提供以下建议。 也是一个非常愚蠢的问题,不知道为什么,但我必须始终指定 find 或 findstr 的路径,这是路径错误,还是什么?只是好奇。 【参考方案1】:

试试这个,把你的转换命令放在循环中,如果输出正常的话,在 handbrakecli 之前删除echo这个词:

@echo off &setlocal
FOR /R "%somepath%" %%G in (*.avi) DO (
    set "fpath=%%G"
    set "fname=%%~nG"
    setlocal enabledelayedexpansion
    if "!fname!"=="!fname:trailer=!" if "!fname!"=="!fname:sample=!" (
        echo handbrakecli.exe "!fpath!" &rem put your conversion  command here
        >>"logfile.log" echo !fname!
    )
    endlocal
)

文件名+文件路径在变量"!fpath!"中。

添加了一些关于 OP 需求的代码:

@echo off &setlocal
rem replace avi with mp4 files in my movie folder
rem grab 4 random folders with avi in them and no mp4

rem Settings for this Batch File
set "moviepath=H:\Movies"
set "logfile=C:\Documents and Settings\%USERNAME%\LogFiles\avi_converter.log"

rem check if log file exists
if not exist "%logfile%" echo(>"%logfile%"

rem create empty convert file
copy nul "convert_movies.bat" >nul 2>&1

rem add echo off
echo @echo off >>"convert_movies.bat"

rem set counter
SET /A COUNT=1

FOR /R "%moviepath%" %%G in (*.avi) DO (
    set "fpath=%%~fG"
    set "fname=%%~nG"
    setlocal enabledelayedexpansion

    rem check if count greater than 4
    if !COUNT! gtr 4 goto:eof

    if "!fname!"=="!fname:trailer=!" if "!fname!"=="!fname:sample=!" (
        rem echo handbrakecli.exe "!fpath!" &rem put your conversion  command here

            rem Send File To HandBrakeCLI
            CALL :DOHandBrakeCLI "!fpath!"

            rem Delete File
            CALL :DeleteOldFile "!fpath!"

            rem Add Log Entry
            CALL :LogEntry "!fpath!"

            rem add line break space
            echo( >>"convert_movies.bat"

            endlocal
            rem increment counter
            SET /A COUNT+=1

    ) else endlocal  
)
rem end main program, to close cmd window replace it with EXIT
goto:eof

:DOHandBrakeCLI
rem skip if the parameter is empty
IF "%~1"=="" goto:eof
For %%A in ("%~1") do (
    Set "Folder=%%~dpA"
    Set  "Name=%%~nxA"
)
rem echo %Folder%%Name%
echo start /b "" "c:\handbrakecli\HandBrakeCLI.exe" -i "%~1" -o "%Folder%%~n1.mp4" --preset="High Profile">>"convert_movies.bat"
exit /b

:DeleteOldFile
rem skip if the parameter is empty
IF "%~1"=="" goto:eof
For %%A in ("%~1") do (
    Set "Folder=%%~dpA"
    Set "Name=%%~nxA"
)
rem sends parameters to deletefile which will make sure new file exists before deleting old one
echo c:\projects\deletefile.bat "%~1" "%Folder%%~n1.mp4">>"convert_movies.bat"
exit /b

:LogEntry
rem skip if the parameter is empty
IF "%~1"=="" goto:eof
echo "%~1">>"%logfile%"
exit /b

【讨论】:

我正在使用此循环创建一个辅助批处理文件,其中将包含要转换的文件列表,然后删除原始文件。这会影响我将这些命令回显到辅助批处理文件的能力吗? @crosenblum - 我进行了编辑:1) 将日志命令放入 2) 错误修复(将 endlocal 放在第一个右括号之后) 检查我的 pastebin,查看我正在使用的代码以及您建议的代码。我已经有了日志文件命令,可以帮助记录、处理删除文件。已经完成了 90%,非常感谢您。现在剩下两件事,将循环限制为 x 次,这样我的电脑就不会超载转换太多,并处理带有不寻常字符的文件名,例如亚洲语言。有什么想法吗? @crosenblum - 进行了编辑并插入了您的代码并进行了一些改进。 我收到几条错误消息,提示系统找不到指定的路径。它还创建批处理文件,但在 echo off 语句的最顶部添加一个空白行。什么是为您提供信用和感谢您的帮助的可接受方式。我打算把它作为一个捆绑包放在 github 上,以帮助人们逐渐将他们的电影/电视节目转换为 mp4 格式。您希望如何被提及?【参考方案2】:

这应该可行:

@echo off
FOR /R "%somepath%" %%G in (*.avi) DO (
echo "%%~nG" |findstr /i "trailer sample">nul || (
  rem do conversion
 )
)

【讨论】:

+1,好主意,但findstr 可能比if ... if... 慢。 %%G 包含完整路径。 感谢您的 cmets - 我将其替换为 %%~nG 。 Findstr 肯定会更慢,但我怀疑每个 AVI 编码都需要一个多小时,所以时间不是一个因素。 :)【参考方案3】:

很难看出你的帖子在哪里是伪代码,哪里是实际代码。

第一个示例仅包含 REM 语句,因此它显然什么也没做也就不足为奇了。

您的第二个和第三个样本实际上是相同的 - 唯一的区别是目标字符串。变量skip 没有设置为Yes 并不奇怪,因为正确的语法是

if %errorlevel% equ 0 set skip=Yes

您发布的语法将 REPORT 表示 skip 未定义 - 它忽略了 Yes

HOWEVER 此语法仅可用于"block statement"OUTSIDE - 即多指令语句(括在括号中)或级联&by&ampersands。首先批处理PARSES 一个完整的语句 - 从FORif 到适当的右括号,然后THEN 执行它。作为PARSING 阶段的一部分,任何%var% - 包括%errorlevel% 都将替换为其在整个语句为parsed 时的值 - 而不是由于for 的操作而改变.

为了在值发生变化时使用它,您需要使用

if errorlevel 1 (do_something) else (do_something_else)

其中do_somethingdo_something_else) 本身可能是复合语句。

if defined variable (do_something) else (do_something_else)

变量在哪里定义或没有定义

setlocal enabledelayedexpansion
....
if !errorlevel! equ x (do_something) else (do_something_else)

 if !var! neq something (do_something) else (do_something_else)

但很有可能

FOR /R "%somepath%" %%G in (*.avi) DO (
 echo(%%G|findstr /i "sample trailer" >nul
 if errorlevel 1 echo %%G
)

会给你一个合适的骨架。

通过FINDSTR 回显文件名并查找“样本”或“预告片”/i 不区分大小写。如果找到任一目标字符串,Findstr 设置错误级别 0,否则设置为 1 - 并且 if errorlevel x 语法适用于循环内 errorlevel 的动态值。

【讨论】:

【参考方案4】:
@ECHO on &SETLOCAL

REM This script was inspired by Endoro's expanded script
(https://***.com/a/16891696/10572786).

REM This batch script will recursively search for all .mp4 files that don't
have (x265) in the file name. Any valid results will be encoded with x265
using FFmpeg. The original .mp4 file will remain unchanged in it's original
folder with the new x265 version.

REM Example: %PATH%\A.mp4 > %PATH%\A(x265).mp4

REM If you don't have ffmpeg.exe on your PC you must download or build it
with Microsoft Visual Studios. I recommend you download and run media
autobuild suite on GitHub: (https://github.com/jb-alvarado/media- 
autobuild_suite).

REM Once ffmpeg is compiled/downloaded make sure to set it's folder path as
an environmental variable in Windows before running the script. Change the
script's working directory to your .mp4 files root folder using the "cd" 
command.

REM !!BEGIN SCRIPT!!

cd /d %USERPROFILE%\Desktop\Vids\
REM or perhaps use [cd /d %OneDrive%\Desktop\Vids]

REM Set mp4PATH to the root folder you wish to recursively search.
SET "mp4PATH=%USERPROFILE%\Desktop\Vids\"

REM Create empty convert file.
COPY NUL "convert_movies.bat" >NUL 2>&1

REM Add ECHO off.
ECHO @ECHO off >>"convert_movies.bat"

REM Recursively search root folder.
FOR /R "%mp4PATH%" %%G IN (*.mp4) DO (
    SET "fpath=%%~fG"
    SET "fname=%%~nG"
    SETLOCAL enabledelayedexpansion

REM Ignore all files that have "(x265)" in the file name.
IF "!fname!"=="!fname:*(x265)=!" (
    CALL :DO_FFmpeg_CLI "!fpath!"
    ECHO(>>"convert_movies.bat"
        ) ELSE ENDLOCAL
    )
)
GOTO:EOF

REM CALL variables for use in FFmpeg's command line.
:DO_FFmpeg_CLI
IF "%~1"=="" GOTO:EOF
FOR %%I IN ("%~1") DO (
    SET "Folder=%%~dpI"
    SET "Name=%%~nxI"
)

REM Export info to "convert_movies.bat and run ffmpeg.exe's command line in the cmd.exe window.
ECHO ffmpeg -y -i "%~1" -c:v libx265 -preset slow -crf
18 -c:a aac "%Folder%%~n1(x265).mp4">>"convert_movies.bat" && ffmpeg |
ffmpeg -y -i "%~1" -c:v libx265 -preset slow
-crf 18 -c:a aac "%Folder%%~n1(x265).mp4"
EXIT /B
PAUSE

【讨论】:

【参考方案5】:

下面的批处理文件解决了原始问题并将转换文件的数量限制为给定的数量(未出现在原始问题中):

@echo off
setlocal EnableDelayedExpansion
rem Insert in the next line the list of files to skip
set skip=/trailer/sample/
set count=0
FOR /R "%somepath%" %%G in (*.avi) DO (
   if /I "!skip:/%%~nG/=!" equ "%skip%" (
      echo Current file name is not in skip variable
      echo Do conversion on: %%G
      set /A count+=1
      if !count! equ 20 goto :endLoop
   )
)
:endLoop
echo Converted files: %count%

【讨论】:

以上是关于批处理文件循环跳过文件,如果名称包含的主要内容,如果未能解决你的问题,请参考以下文章

如何跳过在批处理文件中发现的错误并继续执行命令行?

如果文件夹名称包含Unicode字符,批处理无法正常工作

Bat批处理:批量重命名包含指定名称文件夹里的指定文件

批处理:如何在 FOR 循环中附加字符串

如何在批处理文件中使用for循环列出文件夹中所有文件和目录的名称

批处理文件 FOR 循环改进