批处理 - Ghost文件传递'如果不存在'检查

时间:2017-06-16 17:15:59

标签: batch-file file-exists not-exists

我的代码

我在下面有一些简单的代码:

  1. 检查我的目录中是否存在文件
  2. 运行for循环以获取第一个文件名
  3. 基于文件名的东西
  4. 删除文件
  5. 检查目录中是否存在任何其他文件(如果是,重复,如果没有,继续)

    :MYLOOP
    IF NOT EXIST "%mypath%\*.*" GOTO nofile
    FOR %%F IN ("%mypath%\*.*") DO (
        set filenameWithExt=%%~nxF
        set filename=%%~nF
        set filepath=%%~pF
        )
    do other filename specific tasks
    
    del "%mypath%\%filenameWithExt%"
    
    IF NOT EXIST "%mypath%\*.*" GOTO nofile
    
    GOTO MYLOOP
    
    :nofile
    
  6. 我的问题

    我已经反复使用这个代码,它的功能就像一个魅力,但在我最近的使用中,它似乎找到了一个“幽灵”。文件。如果目录中有无文件(存在单个存档文件夹),则上面步骤1中的if not exist检查仍会以某种方式传递。因此,for循环中的set代码会导致:

      

    系统找不到指定的文件。

    然后看起来好像它试图删除我的目录,说:

      

    \\ mypath *,你确定(是/否)?

    然后我必须手动终止其他自动批处理。

    我的问题

    为什么它会通过if not exist检查,而不是跳到:nofile?

    我怎样才能解释这个幽灵'文件(或者如果它正在检测存档文件夹 - 我怎么能忽略它?)

2 个答案:

答案 0 :(得分:4)

Windows内核,因此Windows命令解释器也解释通配符模式*.*,如*,这意味着任何文件或文件夹。在使用通配符模式*.*时,并不意味着必须存在名称中带有点的文件(或文件夹)。

因此,使用条件IF NOT EXIST "%mypath%\*.*"与使用IF NOT EXIST "%mypath%\*"相同。

IF EXIST "%mypath%\*"通常用于批处理文件中,以验证%mypath%是否指定了文件夹而不是文件,因为此条件会检查是否存在文件夹%mypath%。如果该文件夹存在,则条件为 true ,与该文件夹中的文件和文件夹数无关。

因此,批处理文件顶部的条件不会检查文件夹%mypath%中是否至少有1个文件,它会检查该文件夹是否根本不存在。

您可以使用以下批处理代码,通过使用子程序避免使用延迟扩展。

@echo off
for /F "delims=" %%I in ('dir /A-D /B /ON "%mypath%\*" 2^>nul') do call :ProcessFile "%mypath%\%%I"
goto :EOF

:ProcessFile
set "FilenNmeWithExt=%~nx1"
set "FileName=%~n1"
set "FilePath=%~p1"
rem do other filename specific tasks
del "%~1"
goto :EOF

命令 FOR 执行命令行

dir /A-D /B /ON "%mypath%\*" 2>nul

在后台的单独命令过程中捕获 DIR 的输出,以处理 STDOUT

如果目录根本不存在或者不包含任何文件,

DIR 会输出错误消息来处理 STDERR 。通过使用2>nul将其重定向到设备 NUL 来抑制此错误消息。必须使用插入符>对重定向运算符^进行转义,以便在解析整个 FOR 命令行时首先由Windows命令解释程序解释为文字字符,否则会出现语法错误会是结果。

选项/A-D表示 DIR 应输出所有未设置目录属性的目录条目,即只是文件,而不是文件夹。 /B DIR 的输出更改为裸格式,这意味着只显示没有任何其他数据的文件名。在 DIR 输出整个列表之前,/ON会按文件名对列表进行排序。这个选项在这里不是必需的。

FOR 现在处理 DIR 的捕获输出。因此,当 FOR 正在运行时,删除该目录中的文件并不重要。 FOR 通过 DIR 处理初始列表作为输出。

对于 DIR 输出的每个文件名,执行子例程ProcessFile,就像调用具有该名称的另一个批处理文件一样。传递给子例程的是文件名及其路径。 DIR 只输出没有路径的文件名,而不使用额外的/S来获取指定目录及其所有子目录中所有文件名的列表。

需要 FOR 循环后的命令goto :EOF,以避免在处理完 DIR 输出的所有文件名后落入子程序。< / p>

如果上面的行是批处理文件的最后一行,则不需要子例程之后的命令goto :EOF。但是,如果要添加更多命令行(如下面的另一个子例程),则始终使用goto :EOF结束子例程通常是一种好的做法。对于Windows命令解释器,从其标签开始的子例程在文件中的位置无关紧要。

答案 1 :(得分:2)

if exist测试在目录中查找任何

我重组了你的代码:

:MYLOOP
set "found1="
FOR %%F IN ("%mypath%\*.*") DO (
    set filenameWithExt=%%~nxF
    set filename=%%~nF
    set filepath=%%~pF
    set "found1=Y"
    )
if not defined found1 goto nofile

do other filename specific tasks

del "%mypath%\%filenameWithExt%"
GOTO MYLOOP

:nofile

如果for找不到文件,found1将保持未定义,因此我们转到:nofile标签,否则我们有一个要处理的文件。删除文件后,只需返回到开头,清除标记并重复...