0

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?

Insarov
  • 971
  • 1
  • 10
  • 15
  • Can you split this into two questions please? – Nate Hekman Apr 18 '13 at 16:37
  • Instead of `dir /a /b "%%~fd" 2>null` can you just go `echo %%~nxd`? (I realize that doesn't answer your question, I'm just trying to understand what you're doing.) – Nate Hekman Apr 18 '13 at 16:47
  • Please tell us why you have decided to "lists every file name ... and notifies the user ...". What are you trying to accomplish here? The reason you're getting these random suggestions is because we do not know where the finish line is. If you keep "rewriting every function" this should be a warning sign you have made a wrong decision somewhere, but we can't help you if you don't tell us where you're trying to go. – Dour High Arch Apr 18 '13 at 16:59
  • What I'm trying to do is after the directory is selected: echo each file in that directory, but if it's empty, echo "* is empty". – Insarov Apr 18 '13 at 17:34
  • @Nate Hekman - `echo %%~nxd` seems to produce the same effect. Is it the same thing as I had previously, just shorthand? – Insarov Apr 18 '13 at 18:30

1 Answers1

2

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!

Community
  • 1
  • 1
rojo
  • 24,000
  • 5
  • 55
  • 101
  • This is really brilliant. Solves the latter portion of my question, I definitely wouldn't have thought of that. – Insarov Apr 18 '13 at 17:33
  • @Insarov - If you agree that it's appropriate, please consider [accepting my answer formally](http://meta.stackexchange.com/a/5235/187716). Although I'm still testing and making tweaks here and there. :) – rojo Apr 18 '13 at 17:36
  • @Insarov - I think I'm finished performing my evil experiments on the scripts now. Did you pick your favorite? Do you have any questions about it? – rojo Apr 18 '13 at 18:01
  • I'm crossed between them, but the last one's intriguing. I'm still stuck on the first part of my question though. If the directory's empty, how do I have it echo e.g. "Friday: empty"? Using `| findstr "^" >nul && echo %%~nd || echo Empty: Friday`, it doesn't do anything if a string isn't found. – Insarov Apr 18 '13 at 18:40
  • Sure it does. It echoes `Empty: Friday`. I added an explanation to the top of my answer. Also, see [this page](http://ss64.com/bash/syntax-execute.html) for a more thorough explanation. Perhaps to be safe, we ought to define "empty". Do you consider a directory to be empty if it has no files but does contain folders? Or is it empty only if it contains neither files nor folders? – rojo Apr 18 '13 at 18:48
  • "Empty", meaning no files. Testing the original code in my question, the folder is entirely empty. No files or subfolders or hidden files. But it doesn't do anything when I run the script. But if I add a file to it, it displays that file, and ignores any folders or hidden files. – Insarov Apr 18 '13 at 18:57
  • `o°/` I can't make any of these scripts *not* work. I'm selecting several paths -- my Desktop, a network drive, my Program Files (x86) directory and other paths with spaces... How have you modified the `:getdirs` subroutine in my scripts? – rojo Apr 18 '13 at 19:02
  • I hadn't. Although, for example, using your first script: adding `for /r "O:\Mail\5-Friday" %%d in (*.pdf) do ( dir /a /b "%%~fd" 2>nul | findstr "^" >nul && echo %%~nd )` to `:getdirs` will display any pdfs when I type 'friday'. (I'm just using the specific case for testing for now). But if it's empty, nothing shows. It seems to be checking for subfolders, rather than the directory itself? (If I place an empty folder in \5-Friday\, it'll echo that folder as not empty.) – Insarov Apr 18 '13 at 19:20