Reputation: 31
CMD. How do I check if a directory contains a folder/s (name is not specified)? Other files are ignored.
If this was in the case of any .txt file, it would kind of look like this :
if exist * .txt
How do I do it with "any" folder?
Upvotes: 3
Views: 1874
Reputation: 49085
There are multiple solutions to check if a directory contains subdirectories.
In all solutions below the folder for temporary files referenced with %TEMP%
is used as an example.
Solution 1 using FOR /D:
@echo off
set "FolderCount=0"
for /D %%I in ("%TEMP%\*") do set /A FolderCount+=1
if %FolderCount% == 0 (
echo Temporary files folder has no non-hidden subfolder.
) else if %FolderCount% == 1 (
echo Temporary files folder has one non-hidden subfolder.
) else (
echo Temporary files folder has %FolderCount% non-hidden subfolders.
)
pause
The problem with this solution is that FOR with option /D
to search for directories matching the wildcard pattern *
in specified directory for temporary files ignores the directories with hidden attribute set. For that reason the command SET with the arithmetic expression to increment the value of environment variable FolderCount
by one on each each directory is not executed for a directory with hidden attribute set.
The short version of this solution without counting the folders:
@echo off
for /D %%I in ("%TEMP%\*") do goto HasFolders
echo Temporary files folder has no non-hidden subfolder.
goto EndBatch
:HasFolders
echo Temporary files folder has non-hidden subfolders.
:EndBatch
pause
The loop is exited with command GOTO on FOR has assigned first name of a non-hidden directory to the loop variable.
Solution 2 using FOR /F and DIR:
@echo off
set "FolderCount=0"
for /F "eol=| delims=" %%I in ('dir "%TEMP%" /AD /B 2^>nul') do set /A FolderCount+=1
if %FolderCount% == 0 (
echo Temporary files folder has no subfolder.
) else if %FolderCount% == 1 (
echo Temporary files folder has one subfolder.
) else (
echo Temporary files folder has %FolderCount% subfolders.
)
pause
FOR with option /F
and a set enclosed in '
results in starting in background one more command process with %ComSpec% /c
and the command line within '
appended as additional arguments. So executed is with Windows installed to C:\Windows
:
C:\Windows\System32\cmd.exe /c dir "C:\Users\UserName\AppData\Local\Temp" /AD /B 2>nul
DIR executed by background command process searches
/AD
(attribute directory)/AD
overrides the default /A-H
(all attributes except attribute hidden)/B
which results in ignoring the standard directories .
(current directory) and ..
(parent directory) and printing just the directory names without path.The output of DIR is written to handle STDOUT (standard output) of the started background command process. There is nothing output if the there is no subdirectory in the specified directory.
There is an error message output to handle STDERR (standard error) of background command process if the specified directory does not exist at all. This error message would be redirected by the command process executing the batch file to own STDERR handle and would be output in console window. For that reason 2>nul
is appended to the DIR command line to suppress the error message in background command process by redirecting it from handle STDERR to device NUL.
Read the Microsoft article about Using command redirection operators for an explanation of 2>nul
. The redirection operator >
must be escaped with caret character ^
on FOR command line to be interpreted as literal character when Windows command interpreter processes this command line before executing command FOR which executes the embedded dir
command line with using a separate command process started in background.
FOR with option /F
captures the output written to handle STDOUT of started background command process and processes the output line by line after started cmd.exe
terminated itself after finishing execution of internal command DIR.
Empty lines are ignored by default by FOR which do not occur here.
FOR would split up the line by default into substrings using normal space and horizontal tab character as string delimiters and would assign just first space/tab separated string to specified loop variable I
. This line splitting behavior is unnecessary here and is disabled for that reason by using option delims=
which defines an empty list of string delimiters.
FOR would ignore also lines on which first substring after splitting a line up into substrings starts with default end of line character ;
. The line splitting behavior is already disabled, but the name of directory can start unusually with a semicolon. Such a directory name would be ignored by FOR. Therefore the option eol=|
defines the vertical bar as end of line character which no directory name can have and so no directory is ignored by FOR. See also the Microsoft documentation page Naming Files, Paths, and Namespaces.
The directory name assigned to loop variable I
is not really used because of FOR executes for each directory name just command SET with an arithmetic expression to increment the value of the environment variable FolderCount
by one.
The environment variable FolderCount
contains the number of subfolders in specified directory independent on hidden attribute.
The short version of this solution without counting the folders:
@echo off
for /F "eol=| delims=" %%I in ('dir "%TEMP%" /AD /B 2^>nul') do goto HasFolders
echo Temporary files folder has no subfolder.
goto EndBatch
:HasFolders
echo Temporary files folder has subfolders.
:EndBatch
pause
The loop is exited with command GOTO on FOR has assigned first name of a directory to the loop variable.
Solution 3 using DIR and FINDSTR:
@echo off
dir "%TEMP%" /AD /B 2>nul | %SystemRoot%\System32\findstr.exe /R "^." >nul
if errorlevel 1 (
echo Temporary files folder has no subfolder.
) else (
echo Temporary files folder has subfolders.
)
pause
The output of DIR as explained above executed by cmd.exe
processing the batch file is redirected from STDOUT of command process to STDIN (standard input) of FINDSTR which searches for lines having at least one character. The found lines are all lines with a directory name output by DIR. This search result is of no real interest and therefore redirected to device NUL to suppress it.
FINDSTR exits with 1
if no string could be found and with 0
on having at least one string found. The FINDSTR exit code is assigned by Windows command processor to ERRORLEVEL
which is evaluated with the IF condition.
The IF condition is true if exit value of FINDSTR assigned to ERRORLEVEL
is greater or equal 1
which is the case on no directory found by DIR and so FINDSTR failed to find any line with at least one character.
This solution could be also written as one command line:
dir "%TEMP%" /AD /B 2>nul | %SystemRoot%\System32\findstr.exe /R "^." >nul && echo Temporary files folder has subfolders.|| echo Temporary files folder has no subfolder.
See single line with multiple commands using Windows batch file for an explanation of the operators &&
and ||
used here to evaluate the exit code of FINDSTR.
Additional hints:
It would be good to first check if the directory exists at all before checking if it contains any subdirectories. This can be done in all three solutions above by using first after @echo off
if not exist "%TEMP%\" (
echo Folder "%TEMP%" does not exist.
pause
exit /B
)
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.
cmd /?
dir /?
echo /?
exit /?
findstr /?
for /?
goto /?
if /?
pause /?
set /?
Upvotes: 2
Reputation: 16226
If you just want to use the cmd.exe shell console to see if there are any directories:
DIR /A:D
If you want to check for it in a .bat file script:
SET "HASDIR=false"
FOR /F "eol=| delims=" %%A IN ('DIR /B /A:D') DO (SET "HASDIR=true")
IF /I "%HASDIR%" == "true" (
REM Do things about the directories.
)
ECHO HASDIR is %HASDIR%
Upvotes: 0
Reputation: 125
DIR "your directory" /ad
, for example DIR C:\Users /ad
brings out all folders that are inside C:\Users
Displays a list of files and subdirectories in a directory.
DIR [ drive:][path][filename] [/A[[:]attributes]] [/B] [/C] [/D] [/L] [/N]
[/O[[:]sortorder]] [/P] [/Q] [/R] [/S] [/T[[:]timefield]] [/W] [/X] [/4]
[drive:][path][filename]
Specifies drive, directory, and/or files to list.
/A Displays files with specified attributes.
attributes D Directories R Read-only files
H Hidden files A Files ready for archiving
S System files I Not content indexed files
L Reparse Points
Upvotes: 0