Is there any way to find out if a file is a directory?
I have the file name in a variable. In Perl I can do this:
if(-d $var) { print "it's a directory\n" }
Is there any way to find out if a file is a directory?
I have the file name in a variable. In Perl I can do this:
if(-d $var) { print "it's a directory\n" }
You can do it like so:
IF EXIST %VAR%\NUL ECHO It's a directory
However, this only works for directories without spaces in their names. When you add quotes round the variable to handle the spaces it will stop working. To handle directories with spaces, convert the filename to short 8.3 format as follows:
FOR %%i IN (%VAR%) DO IF EXIST %%~si\NUL ECHO It's a directory
The %%~si converts %%i to an 8.3 filename. To see all the other tricks you can perform with FOR variables enter HELP FOR at a command prompt.
(Note - the example given above is in the format to work in a batch file. To get it work on the command line, replace the %% with % in both places.)
Here's a script that uses FOR to build a fully qualified path, and then pushd to test whether the path is a directory. Notice how it works for paths with spaces, as well as network paths.
@echo off
if [%1]==[] goto usage
for /f "delims=" %%i in ("%~1") do set MYPATH="%%~fi"
pushd %MYPATH% 2>nul
if errorlevel 1 goto notdir
goto isdir
:notdir
echo not a directory
goto exit
:isdir
popd
echo is a directory
goto exit
:usage
echo Usage: %0 DIRECTORY_TO_TEST
:exit
Sample output with the above saved as "isdir.bat":
C:\>isdir c:\Windows\system32
is a directory
C:\>isdir c:\Windows\system32\wow32.dll
not a directory
C:\>isdir c:\notadir
not a directory
C:\>isdir "C:\Documents and Settings"
is a directory
C:\>isdir \
is a directory
C:\>isdir \\ninja\SharedDocs\cpu-z
is a directory
C:\>isdir \\ninja\SharedDocs\cpu-z\cpuz.ini
not a directory
CD returns an EXIT_FAILURE when the specified directory does not exist. And you got conditional processing symbols, so you could do like the below for this.
SET cd_backup=%cd%
(CD "%~1" && CD %cd_backup%) || GOTO Error
:Error
CD %cd_backup%
I think there is some difficulty using the "NUL" tecnique when there are SPACES in the directory name, such as "Documents and Settings."
I am using Windows XP service pack 2 and launching the cmd prompt from %SystemRoot%\system32\cmd.exe
Here are some examples of what DID NOT work and what DOES WORK for me:
(These are all demonstrations done "live" at an interactive prompt. I figure that you should get things to work there before trying to debug them in a script.)
This DID NOT work:
D:\Documents and Settings>if exist "D:\Documents and Settings\NUL" echo yes
This DID NOT work:
D:\Documents and Settings>if exist D:\Documents and Settings\NUL echo yes
This DOES work (for me):
D:\Documents and Settings>cd ..
D:\>REM get the short 8.3 name for the file
D:\>dir /x
Volume in drive D has no label.
Volume Serial Number is 34BE-F9C9
Directory of D:\
09/25/2008 05:09 PM <DIR> 2008
09/25/2008 05:14 PM <DIR> 200809~1.25 2008.09.25
09/23/2008 03:44 PM <DIR> BOOST_~3 boost_repo_working_copy
09/02/2008 02:13 PM 486,128 CHROME~1.EXE ChromeSetup.exe
02/14/2008 12:32 PM <DIR> cygwin
[[Look right here !!!! ]]
09/25/2008 08:34 AM <DIR> DOCUME~1 Documents and Settings
09/11/2008 01:57 PM 0 EMPTY_~1.TXT empty_testcopy_file.txt
01/21/2008 06:58 PM <DIR> NATION~1 National Instruments Downloads
10/12/2007 11:25 AM <DIR> NVIDIA
05/13/2008 09:42 AM <DIR> Office10
09/19/2008 11:08 AM <DIR> PROGRA~1 Program Files
12/02/1999 02:54 PM 24,576 setx.exe
09/15/2008 11:19 AM <DIR> TEMP
02/14/2008 12:26 PM <DIR> tmp
01/21/2008 07:05 PM <DIR> VXIPNP
09/23/2008 12:15 PM <DIR> WINDOWS
02/21/2008 03:49 PM <DIR> wx28
02/29/2008 01:47 PM <DIR> WXWIDG~2 wxWidgets
3 File(s) 510,704 bytes
20 Dir(s) 238,250,901,504 bytes free
D:\>REM now use the \NUL test with the 8.3 name
D:\>if exist d:\docume~1\NUL echo yes
yes
This works, but it's sort of silly, because the dot already implies i am in a directory:
D:\Documents and Settings>if exist .\NUL echo yes
Based on this article titled "How can a batch file test existence of a directory" it's "not entirely reliable".
BUT I just tested this:
@echo off
IF EXIST %1\NUL goto print
ECHO not dir
pause
exit
:print
ECHO It's a directory
pause
and it seems to work
I would like to post my own function script about this subject hope to be useful for someone one day.
@pushd %~dp1
@if not exist "%~nx1" (
popd
exit /b 0
) else (
if exist "%~nx1\*" (
popd
exit /b 1
) else (
popd
exit /b 3
)
)
This batch script checks if file/folder is exist and if it is a file or a folder.
Usage:
script.bat "PATH"
Exit code(s):
0: file/folder doesn't exist.
1: exists, and it is a folder.
3: exists, and it is a file.
If your objective is to only process directories then this will be useful.
This is taken from the https://ss64.com/nt/for_d.html
Example... List every subfolder, below the folder C:\Work\ that has a name starting with "User":
CD \Work FOR /D /r %%G in ("User*") DO Echo We found
FOR /D or FOR /D /R
@echo off
cd /d "C:\your directory here"
for /d /r %%A in ("*") do echo We found a folder: %%~nxA
pause
Remove /r to only go one folder deep. The /r switch is recursive and undocumented in the command below.
The for /d help taken from command for /?
FOR /D %variable IN (set) DO command [command-parameters]
If set contains wildcards, then specifies to match against directory names instead of file names.
I was looking for this recently as well, and had stumbled upon a solution which has worked for me, but I do not know of any limitations it has (as I have yet to discover them). I believe this answer is similar in nature to TechGuy's answer above, but I want to add another level of viability. Either way, I have had great success expanding the argument into a full fledged file path, and I believe you have to use setlocal enableextensions for this to work properly.
Using below I can tell if a file is a directory, or opposite. A lot of this depends on what the user is actually needing. If you prefer to work with a construct searching for errorlevel vs && and || in your work you can of course do so. Sometimes an if construct for errorlevel can give you a little more flexibility since you do not have to use a GOTO command which can sometimes break your environment conditions.
@Echo Off
setlocal enableextensions
Dir /b /a:D "%~f1" && Echo Arg1 is a Folder || Echo Arg1 is NOT a Folder
Dir /b /a:-D "%~f1" && Echo Arg1 is a File || Echo Arg1 is NOT a File
pause
Using this you could simply drag and drop your file(s) onto the tool you are building to parse them out. Conversely, if you are using other means to comb your file structure and you already have the file and are not dragging/dropping them onto the batch file, you could implement this:
@Echo Off
setlocal enableextensions
Dir /b /s "C:\SomeFolderIAmCombing\*" >"%~dp0SomeFiletogoThroughlater.txt"
For /f "Usebackq Delims=" %%a in ("%~dp0SomeFiletogoThroughlater.txt") do (
Call:DetectDir "%%a"
)
REM Do some stuff after parsing through Files/Directories if needed.
REM GOTO:EOF below is used to skip all the subroutines below.
REM Using ' CALL:DetectDir "%%a" ' with the for loop keeps the for
REM loop environment running in the background while still parsing the given file
REM in a clean environment where GOTO and other commmands do not need Variable Expansion.
GOTO:EOF
:DetectDir [File or Folder being checked]
REM Checks if Arg1 is a Directory. If yes, go to Dir coding. If not, go to File coding.
Dir /b /a:D "%~f1" && Echo Arg1 is a Folder & GOTO:IsDir || Echo Arg1 is NOT a Folder & GOTO:IsFile
REM Checks if Arg1 is NOT a Directory. If Yes, go to File coding. If not, go to Dir coding
Dir /b /a:-D "%~f1" && Echo Arg1 is a File & GOTO:IsFile || Echo Arg1 is NOT a File & GOTO:IsDir
:IsDir
REM Do your stuff to the Folder
GOTO:EOF
:IsFile
REM do your stuff to the File
GOTO:EOF