Question

I'm trying to write a script that lists every file name in a specified folder, and notifies the user if that folder is empty. So far I've got:

for /r "O:\Mail\5-Friday" %%d in (*.pdf) do (
    dir /a /b "%%~fd" 2>nul | findstr "^" >nul && echo %%~nd || echo Empty: Friday
)

but I've no idea where to put the if, else operators.

And is there a way to specify a folder based on user input without rewriting every function for each folder? So instead of:

if /i {%ANS%}=={thursday} (goto :thursday)
if /i {%ANS%}=={friday} (goto :friday)
:thursday
    <do stuff>
:friday
    <do the same stuff as thursday, but a different directory>

etc, I could write one function with variables in place of paths, assign the directory to a variable, and easily add/remove folders in the code as necessary?

Was it helpful?

Solution

To address the first part of your question, "where to put the if, else operators"... The notation of

command | findstr >nul && echo success || echo fail

... is shorthand for

command | findstr >nul
if ERRORLEVEL 1 (
    echo fail
) else (
    echo success
)

The magic that happens is in the conditional execution operators, the && and ||. If findstr exits with status zero, then a match was found. Therefore, execute the stuff after &&. Otherwise, status is non-zero, no match was found, so execute the stuff after ||. See how that works?


For the second part, here's a typical way to prompt the user to provide entry based on a finite number of choices.

@echo off
setlocal

:begin
set /p "day=What day? "
for %%I in (monday tuesday wednesday thursday friday) do (
    if /i "%day%" equ "%%I" goto %%I
)
goto begin

:monday
call :getdirs "O:\Mail\1-Monday"
goto :EOF

:tuesday
call :getdirs "O:\Mail\2-Tuesday"
goto :EOF

:wednesday
call :getdirs "O:\Mail\3-Wednesday"
goto :EOF

:thursday
call :getdirs "O:\Mail\4-Thursday"
goto :EOF

:friday
call :getdirs "O:\Mail\5-Friday"
goto :EOF

:getdirs <path>
setlocal enabledelayedexpansion
for /f "delims=" %%I in ('dir /b /s /ad "%~1"') do (
    dir /b "%%I" 2>NUL | findstr "^" >NUL || echo %%I has no files
)
goto :EOF

Or, even hacksier, I'll do something you probably weren't expecting was possible. I'll have the script open a folder selection dialog to allow the user to select the directory to scan. It's a batch / JScript hybrid script.

If you wish, you can set the root of the folder browser to a ShellSpecialConstants folder by changing the last argument in the next-to-the-last line. Using a value of 0x11 makes the root your system's drives. No value or a value of 0x00 makes the root "Desktop". Or leave the script as-is to set the root as "O:\Mail".

@if (@a==@b) @end /*

:: fchooser2.bat
:: batch portion

@echo off
setlocal

set initialDir="O:\Mail"

for /f "delims=" %%I in ('cscript /nologo /e:jscript "%~f0" "%initialDir%"') do (
    call :getdirs "%%I"
)

exit /b

:getdirs <path>
setlocal enabledelayedexpansion
for /f "delims=" %%I in ('dir /b /s /ad "%~1"') do (
    dir /b "%%I" 2>NUL | findstr "^" >NUL || (

        rem This is where you put code to handle empty directories.
        echo %%I has no files

    )
)
goto :EOF

:: JScript portion */

var shl = new ActiveXObject("Shell.Application");
var hint = 'Double-click a folder to expand, and\nchoose a folder to scan for empty directories';
var folder = shl.BrowseForFolder(0, hint, 0, WSH.Arguments(0));
WSH.Echo(folder ? folder.self.path : '');

Edit Since apparently BrowseForFolder accepts an absolute directory, there's really no benefit to using PowerShell / C#. The hybrid batch / PowerShell / C# script shall henceforth be retired to the revision history.

This is fun!

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top