Search code examples
batch-fileif-statementexists

Test IF file exist, del this local file


This question is related to Test IF file exist, ELSE xcopy these two files.

Background: On occasion I choose to run aGallery-dl.bat in a given folder (just one in each of 100's of folders). It first deletes Folder.jpg then renames Folder2.jpg to Folder.jpg. This has the effect of a red X being replaced by a yellow ! when viewing the folder with parent folder selected in File Explorer. Secondly, it calls gallery-dl.exe. I use going from red X to yellow ! to let me know I've run aGallery-dl.bat at least once. If aGallery-dl.bat completes successfully, it finally deletes the Folder.jpg (currently yellow !), and now the representative contents of the folder (usually DeviantArt .jpg's) are visible. All is well.

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

Problem: Restating, Gallery-dl.bat is in each of 100's of folders. On occasion, I run one of these from within it's local folder. Line 5, if the call to the web site is successful, gallery-dl.exe creates zzzGDB.sqlite3 within the local folder.

In the previous code, when aGallery-dl.bat completed, it would just delete the Folder.jpg. This assumes the call to the web page was successful. On rare occasion, the call to the web page will fail for any number of reasons, though at close (due to that final del .\Folder.jpg), it will still delete folder.jpg.

If zzzGDB.sqlite3 was not created/not present, I need the Folder.jpg (yellow !) to remain.

So, in the below code (line 6, now blank), I've lopped off the final del .\Folder.jpg and am trying to plug-in the provided code beginning at line 7, inserting a test for zzzGDB.sqlite. If found, del .\Folder.jpg. If not found, no action is taken against folder.jpg (it remains).
(The rem statement at the very bottom is just acting as a placeholder for my own knowledge.)

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

Note: Currently, the modified code goes back through every single folder within U:\11Web\gallery-dl\deviantart\*. This action should be reserved only to the local folder. I'm guessing the below is the issue.

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

I don't know how to remove it and still implement everything after do?

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

Solution

  • I suggest to use following lines for 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
    

    The first two lines define the execution environment for the batch file.

    The third line with command PUSHD pushes the current directory path on stack and sets the directory of the executed batch file as current directory. This works even on batch file being stored on a network resource accessed using a UNC path, except there is a network problem on execution of that command line.

    The command exit /B is executed in case of an error to immediately exit processing of the batch file on batch file directory could not be set as current directory. The Windows command processor runs implicitly the command ENDLOCAL in this case.

    See Single line with multiple commands using Windows batch file for an explanation of operator || which results in conditionally executing exit /B only if pushd exited with a non-zero exit code indicating an error.

    The fourth command line with MOVE does not really move the data of file Folder2.jpg to file with name Folder.jpg. In real it just updates the file system in this case as done also by the two commands del .\Folder.jpg and ren .\Folder2.jpg Folder.jpg in your batch file. This is just a very little bit faster method to replace one file by another file with the advantage that Folder.jpg must not exist at all for success without displaying an error message as done by command DEL on file Folder.jpg not existing.

    The FOR command line determines the name of the current folder without path and assigns it to environment variable FOLDER. This is a much faster and safer solution then using the command line:

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

    The command line above results in starting in background one more command process with %ComSpec% /c and the command line between ' appended as additional arguments. So there is executed in background with Windows installed to C:\Windows:

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

    The started cmd.exe executes internal command cd which outputs the full qualified folder name of current directory to handle STDOUT of background command process. This output is captured by cmd.exe processing the batch file and is processed by for after started cmd.exe closed itself after finishing execution of command CD.

    The command FOR would split up the folder path into substrings (tokens) using normal space and horizontal tab as string delimiters, would look next if the first space/tab delimited string starts with a semicolon in which case the captured line would be ignored for further processing, and would assign otherwise just the first space/tab delimited string to loop variable i. So if the full qualified folder name of current directory would contain a space, this command line would fail to determine the folder name of current directory without path.

    There is the dynamic variable CD of which value can be referenced with %CD%. The value is the full qualified folder name of current directory not ending with a backslash, except the root directory of a drive is the current directory. That would be identical to %~dp0 for batch file aGallery-dl.bat with the difference that %~dp0 expands to full qualified name of batch file folder always with a backslash at end.

    However, neither dynamic variable CD nor %~dp0 nor execution of command CD in a separate command process in background are really useful to get name of current directory (= batch file directory) without path. The best method is using:

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

    This simple FOR does nothing else than getting name of current folder without path with a very fast executed file system query and assigning it to environment variable FOLDER.

    Note: for %%I in ("%~dp0.") do set "FOLDER=%%~nxI" could be also used to get folder name without path of folder containing currently executed batch file if the current directory would not be the batch file directory.

    The sixth command line executes gallery-dl.exe with various parameters (arguments).

    Please note that "https://www.deviantart.com/"%FOLDER%"/gallery/all" is in real an invalid argument string. It is not valid to have " inside a URL. The character " is never valid inside an argument string which references a file or folder. This syntax error is detected and automatically fixed which is the reason why the command line in your batch file works at all. The correct argument string is "https://www.deviantart.com/%FOLDER%/gallery/all" with one " at beginning and one " at end and no double quote inside the argument string enclosed in double quotes.

    There is standard for console applications to exit with value 0 on success and a greater value like 1 on an error. I don't know if this is true also for gallery-dl.exe, but I assume that with the command line:

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

    if not errorlevel 1 checks if exit code of gallery-dl.exe assigned to dynamic variable errorlevel is NOT greater or equal 1 which means less than 1 which means equal 0 (on executable never exiting with a negative value which is not recommended to do by a program on any operating system) which means no error occurred during execution of gallery-dl.exe. Please read the documentation of gallery-dl.exe regarding to exit codes of this program or find it out with several executions in a command prompt window and using echo Exit code is: %errorlevel% after each execution of gallery-dl.exe with success or an error (like a wrong URL).

    That condition should be already enough. But there is used one more condition to check for existence of the file zzzGDB.sqlite3 in current directory only before deleting the file Folder.jpg in the current directory which is the batch file directory.

    Please read issue 2 in this answer for the reason writing in batch file

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

    instead of

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

    The code above works also, but requires more CPU cycles for being processed by Windows command processor than the single line with two IF commands and one DEL command on one command line.

    The last but one line pops the full qualified folder name of initial current directory from stack and sets it again as current directory and the last line restores initial execution environment on starting the batch file.

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

    • call /?... explains %~dp0 ... drive and path of argument 0 ... full batch file path.
    • del /?
    • echo /?
    • endlocal /?
    • exit /?
    • for /?
    • move /?
    • popd /?
    • pushd /?
    • set /?
    • setlocal /?