【问题标题】:Test IF file exist, del this local file测试if文件存在,删除这个本地文件
【发布时间】:2020-09-18 11:55:30
【问题描述】:

这个问题与Test IF file exist, ELSE xcopy these two files有关。

背景:有时我会选择在给定文件夹中运行aGallery-dl.bat(100 个文件夹中的每个文件夹中只有一个)。它首先删除Folder.jpg,然后将Folder2.jpg 重命名为Folder.jpg。当查看在文件资源管理器中选择了父文件夹的文件夹时,这会导致红色 X 被黄色 ! 取代。其次,它调用gallery-dl.exe。我使用从红色 X 变为黄色 ! 来让我知道我至少运行了一次 aGallery-dl.bat。如果aGallery-dl.bat 成功完成,它最终会删除Folder.jpg(当前为黄色),现在可以看到文件夹的代表内容(通常是DeviantArt .jpg 的)。一切都很好。

rem @echo off
del .\Folder.jpg
ren .\Folder2.jpg Folder.jpg
FOR /F %%i IN ('cd') DO set FOLDER=%%~nxi
"C:\Program Files (x86)\gallery-dl\gallery-dl.exe" -d "U:\11Web\gallery-dl" --download-archive ".\aGDB.sqlite3" "https://www.deviantart.com/"%FOLDER%"/gallery/all"
del .\Folder.jpg

问题:重申,Gallery-dl.bat 位于 100 个文件夹中。有时,我会从它的本地文件夹中运行其中一个。第5行,如果调用网站成功,gallery-dl.exe会在本地文件夹中创建zzzGDB.sqlite3

在前面的代码中,当aGallery-dl.bat完成时,它只会删除Folder.jpg。这假设对网页的调用是成功的。在极少数情况下,由于多种原因,对网页的调用会失败,但在关闭时(由于最后一个del .\Folder.jpg),它仍会删除folder.jpg

如果 zzzGDB.sqlite3 没有创建/不存在,我需要Folder.jpg(黄色 ) 留下来。

因此,在下面的代码(第 6 行,现在为空白)中,我已经删除了最后的 del .\Folder.jpg,并尝试从第 7 行开始插入提供的代码,插入一个针对 zzzGDB.sqlite 的测试。如果找到,del .\Folder.jpg。如果未找到,则不会对 folder.jpg 采取任何措施(它仍然存在)。
(最底部的rem 声明只是作为我自己知识的占位符。)

rem @echo off
del .\Folder.jpg
ren .\Folder2.jpg Folder.jpg
FOR /F %%i IN ('cd') DO set FOLDER=%%~nxi
"C:\Program Files (x86)\gallery-dl\gallery-dl.exe" -d "U:\11Web\gallery-dl" --download-archive ".\zzzGDB.sqlite3" "https://www.deviantart.com/"%FOLDER%"/gallery/all"

setlocal EnableExtensions DisableDelayedExpansion
for /D %%I in ("U:\11Web\gallery-dl\deviantart\*") do (
    if exist "%%I\zzzGDB.sqlite3" (
        del "%%I\Folder.jpg"
    )
rem 
)
endlocal

注意:目前,修改后的代码会遍历U:\11Web\gallery-dl\deviantart\* 中的每个文件夹。此操作应仅保留给本地文件夹。我猜下面是问题所在。

for /D %%I in ("U:\11Web\gallery-dl\deviantart\*")

我不知道如何删除它并在do 之后仍然实现所有内容?

do (
if exist ".\zzzGDB.sqlite3" (
    del ".\Folder.jpg"
)
rem 
)

【问题讨论】:

  • 圣烟。我回答了我自己的问题。最后一次奏效了。留下答案供他人使用。
  • 请将其作为答案发布,并通过单击旁边的复选框将该答案标记为已接受。

标签: batch-file if-statement exists


【解决方案1】:

我建议aGallery-dl.bat 使用以下行。

@echo off
setlocal EnableExtensions DisableDelayedExpansion
pushd "%~dp0" || exit /B
move /Y "Folder2.jpg" "Folder.jpg"
for %%I in (.) do set "FOLDER=%%~nxI"
"%ProgramFiles(x86)%\gallery-dl\gallery-dl.exe" -d "U:\11Web\gallery-dl" --download-archive "%~dp0zzzGDB.sqlite3" "https://www.deviantart.com/%FOLDER%/gallery/all"
if not errorlevel 1 if exist "zzzGDB.sqlite3" del "Folder.jpg"
popd
endlocal

前两行定义批处理文件的执行环境。

第三行命令PUSHD将当前目录路径压栈,并将执行的批处理文件的目录设置为当前目录。这甚至适用于存储在使用UNC 路径访问的网络资源上的批处理文件,除非在执行该命令行时出现网络问题。

命令exit /B在出错的情况下立即退出批处理文件的处理,批处理文件目录不能设置为当前目录。在这种情况下,Windows 命令处理器隐式运行命令 ENDLOCAL

请参阅 Single line with multiple commands using Windows batch file 以了解运算符 || 的说明,这将导致有条件地执行 exit /B,仅当 pushd 以非零退出代码指示错误时退出。

带有 MOVE 的第四个命令行并没有真正将文件 Folder2.jpg 的数据移动到名称为 Folder.jpg 的文件中。实际上,在这种情况下,它只是更新文件系统,这也是通过批处理文件中的两个命令del .\Folder.jpgren .\Folder2.jpg Folder.jpg 完成的。这只是将一个文件替换为另一个文件的一种更快的方法,其优点是 Folder.jpg 必须完全不存在才能成功,而不会像文件 @ 上的命令 DEL 那样显示错误消息987654337@ 不存在。

FOR 命令行确定当前文件夹的名称,不带路径,并将其分配给环境变量FOLDER。这是一个比使用命令行更快、更安全的解决方案:

FOR /F %%i IN ('cd') DO set FOLDER=%%~nxi

上面的命令行导致在后台启动另一个命令进程,其中%ComSpec% /c' 之间的命令行作为附加参数附加。所以在后台执行,Windows 安装到C:\Windows:

C:\Windows\System32\cmd.exe /c cd

启动的cmd.exe执行内部命令cd输出当前目录的全限定文件夹名来处理后台命令进程的STDOUT。此输出由处理批处理文件的cmd.exe 捕获,并在启动后由for 处理cmd.exe 在完成命令CD 执行后自行关闭。

命令 FOR 将使用普通空格和水平制表符作为字符串分隔符将文件夹路径拆分为子字符串(标记),如果第一个空格/制表符分隔的字符串以分号开头在这种情况下,捕获的行将被忽略以进行进一步处理,否则只会将第一个空格/制表符分隔的字符串分配给循环变量i。因此,如果当前目录的完全限定文件夹名称包含空格,则此命令行将无法确定当前目录的文件夹名称而没有路径。

有一个动态变量CD,它的值可以被%CD%引用。该值是当前目录的完整限定文件夹名称以反斜杠结尾,除了驱动器的根目录是当前目录。这与批处理文件aGallery-dl.bat%~dp0 相同,不同之处在于%~dp0 扩展为批处理文件文件夹的完整限定名称总是,末尾带有反斜杠。

然而,无论是动态变量CD 还是%~dp0 或者在后台单独的命令进程中执行命令CD对于获取当前目录的名称(=批处理文件目录)都不是真正有用的没有路径。最好的方法是使用:

for %%I in (.) do set "FOLDER=%%~nxI"

这个简单的 FOR 除了通过非常快速执行的文件系统查询获取当前文件夹的名称(没有路径)并将其分配给环境变量 FOLDER 之外,什么也不做。

注意:如果当前目录不是批处理文件目录,for %%I in ("%~dp0.") do set "FOLDER=%%~nxI" 也可用于获取包含当前执行的批处理文件的文件夹名称而不包含文件夹路径。

第六条命令行使用各种参数(参数)执行gallery-dl.exe

请注意"https://www.deviantart.com/"%FOLDER%"/gallery/all" 实际上是一个无效的参数字符串。在URL 中包含" 是无效的。字符 " 在引用文件或文件夹的参数字符串中永远无效。检测到此语法错误并自动修复,这就是批处理文件中的命令行完全可以工作的原因。正确的参数字符串是"https://www.deviantart.com/%FOLDER%/gallery/all",开头有一个",结尾有一个",并且在用双引号括起来的参数字符串中没有双引号。

有标准的控制台应用程序在成功时以 0 的值退出,在错误时以更大的值(如 1)退出。我不知道gallery-dl.exe 是否也是如此,但我假设使用命令行:

if not errorlevel 1 if exist "zzzGDB.sqlite3" del "Folder.jpg"

if not errorlevel 1 检查 if 分配给动态变量 errorlevelgallery-dl.exe 的退出代码是否不大于或等于 1 这意味着 小于 1 这意味着 等于 0(在可执行文件上永远不会以负值退出,不建议在任何操作系统上的程序执行此操作)这意味着 没有错误 在执行gallery-dl.exe 期间发生。请阅读gallery-dl.exe 的文档以了解该程序的退出代码,或在命令提示符窗口中多次执行并在每次执行gallery-dl.exe 成功或错误(如错误的URL)后使用echo Exit code is: %errorlevel% .

这个条件应该已经足够了。但是在删除当前目录(即批处理文件目录)中的文件Folder.jpg之前,使用了另外一个条件来检查当前目录中的文件zzzGDB.sqlite3是否存在。

请阅读this answer中的issue 2,了解以批处理文件写入的原因

if not errorlevel 1 if exist "zzzGDB.sqlite3" del "Folder.jpg"

而不是

if not errorlevel 1 (
    if exist "zzzGDB.sqlite3" (
        del "Folder.jpg"
    )
)

上面的代码也可以工作,但需要更多的 CPU 周期才能被 Windows 命令处理器处理,而不是在一个命令上包含两个 IF 命令和一个 DEL 命令的单行代码行。

最后一行从堆栈中弹出初始当前目录的完整限定文件夹名称并将其再次设置为当前目录,最后一行在启动批处理文件时恢复初始执行环境。

要了解所使用的命令及其工作原理,请打开command prompt 窗口,在其中执行以下命令,并仔细阅读每个命令显示的所有帮助页面。

  • call /?... 解释 %~dp0 ... 参数 0 的驱动器和路径 ... 完整的批处理文件路径。
  • del /?
  • echo /?
  • endlocal /?
  • exit /?
  • for /?
  • move /?
  • popd /?
  • pushd /?
  • set /?
  • setlocal /?

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-11-19
    • 2012-07-18
    • 1970-01-01
    • 1970-01-01
    • 2016-07-03
    • 2011-12-25
    • 1970-01-01
    相关资源
    最近更新 更多