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.)
This works:
if exist %1\* echo Directory
Works with directory names that contains spaces:
C:\>if exist "c:\Program Files\*" echo Directory
Directory
Note that the quotes are necessary if the directory contains spaces:
C:\>if exist c:\Program Files\* echo Directory
Can also be expressed as:
C:\>SET D="C:\Program Files"
C:\>if exist %D%\* echo Directory
Directory
This is safe to try at home, kids!
Recently failed with different approaches from the above. Quite sure they worked in the past, maybe related to dfs here. Now using the files attributes and cut first char
@echo off
SETLOCAL ENABLEEXTENSIONS
set ATTR=%~a1
set DIRATTR=%ATTR:~0,1%
if /I "%DIRATTR%"=="d" echo %1 is a folder
:EOF
Further to my previous offering, I find this also works:
if exist %1\ echo Directory
No quotes around %1 are needed because the caller will supply them. This saves one entire keystroke over my answer of a year ago ;-)
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
This works perfectly
if exist "%~1\" echo Directory
we need to use %~1 to remove quotes from %1, and add a backslash at end. Then put thw whole into qutes again.
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
This works and also handles paths with spaces in them:
dir "%DIR%" > NUL 2>&1
if not errorlevel 1 (
echo Directory exists.
) else (
echo Directory does not exist.
)
Probably not the most efficient but easier to read than the other solutions in my opinion.
A variation of @batchman61's approach (checking the Directory attribute).
This time I use an external 'find' command.
(Oh, and note the &&
trick. This is to avoid the long boring IF ERRORLEVEL
syntax.)
@ECHO OFF
SETLOCAL EnableExtentions
ECHO.%~a1 | find "d" >NUL 2>NUL && (
ECHO %1 is a directory
)
Outputs yes on:
I use this:
if not [%1] == [] (
pushd %~dpn1 2> nul
if errorlevel == 1 pushd %~dp1
)
A very simple way is to check if the child exists.
If a child does not have any child, the exist
command will return false.
IF EXIST %1\. (
echo %1 is a folder
) else (
echo %1 is a file
)
You may have some false negative if you don't have sufficient access right (I have not tested it).
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
Here's my solution:
REM make sure ERRORLEVEL is 0
TYPE NUL
REM try to PUSHD into the path (store current dir and switch to another one)
PUSHD "insert path here..." >NUL 2>&1
REM if ERRORLEVEL is still 0, it's most definitely a directory
IF %ERRORLEVEL% EQU 0 command...
REM if needed/wanted, go back to previous directory
POPD
If you can cd
into it, it's a directory:
set cwd=%cd%
cd /D "%1" 2> nul
@IF %errorlevel%==0 GOTO end
cd /D "%~dp1"
@echo This is a file.
@goto end2
:end
@echo This is a directory
:end2
@REM restore prior directory
@cd %cwd%
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.
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%
Under Windows 7 and XP, I can't get it to tell files vs. dirs on mapped drives. The following script:
@echo off if exist c:\temp\data.csv echo data.csv is a file if exist c:\temp\data.csv\ echo data.csv is a directory if exist c:\temp\data.csv\nul echo data.csv is a directory if exist k:\temp\nonexistent.txt echo nonexistent.txt is a file if exist k:\temp\something.txt echo something.txt is a file if exist k:\temp\something.txt\ echo something.txt is a directory if exist k:\temp\something.txt\nul echo something.txt is a directory
produces:
data.csv is a file something.txt is a file something.txt is a directory something.txt is a directory
So beware if your script might be fed a mapped or UNC path. The pushd solution below seems to be the most foolproof.
This is the code that I use in my BATCH files
```
@echo off
set param=%~1
set tempfile=__temp__.txt
dir /b/ad > %tempfile%
set isfolder=false
for /f "delims=" %%i in (temp.txt) do if /i "%%i"=="%param%" set isfolder=true
del %tempfile%
echo %isfolder%
if %isfolder%==true echo %param% is a directory
```
Ok... the 'nul' trick doesn't work if you use quotes in names, which accounts for most files with long file names or spaces.
For example,
if exist "C:\nul" echo Directory
does nothing, but
if exist C:\nul echo Directory
works.
I finally came up with this, which seemed to work for all cases:
for /f %%i in ('DIR /A:D /B %~dp1 ^| findstr /X /c:"%~nx1"') do echo Directory
or if you can assure you meet all of the requirements for 'nul' a solution is:
if exist %~sf1\nul echo Directory
Put these into a batch file like 'test.bat' and do 'test.bat MyFile'.
Here is my solution after many tests with if exist, pushd, dir /AD, etc...
@echo off
cd /d C:\
for /f "delims=" %%I in ('dir /a /ogn /b') do (
call :isdir "%%I"
if errorlevel 1 (echo F: %%~fI) else echo D: %%~fI
)
cmd/k
:isdir
echo.%~a1 | findstr /b "d" >nul
exit /b %errorlevel%
:: Errorlevel
:: 0 = folder
:: 1 = file or item not found
One issue with using %%~si\NUL
method is that there is the chance that it guesses wrong. Its possible to have a filename shorten to the wrong file. I don't think %%~si
resolves the 8.3 filename, but guesses it, but using string manipulation to shorten the filepath. I believe if you have similar file paths it may not work.
An alternative method:
dir /AD %F% 2>&1 | findstr /C:"Not Found">NUL:&&(goto IsFile)||(goto IsDir)
:IsFile
echo %F% is a file
goto done
:IsDir
echo %F% is a directory
goto done
:done
You can replace (goto IsFile)||(goto IsDir)
with other batch commands:
(echo Is a File)||(echo is a Directory)
Can't we just test with this :
IF [%~x1] == [] ECHO Directory
It seems to work for me.