如何在批处理脚本中测试文件是否为目录?


76

有没有办法找出文件是否是目录?

我在变量中有文件名。在Perl中,我可以这样做:

if(-d $var) { print "it's a directory\n" }

Answers:


55

您可以这样做:

IF EXIST %VAR%\NUL ECHO It's a directory

但是,这仅适用于名称中没有空格的目录。当您在引号周围加上变量以处理空格时,它将停止工作。要处理带有空格的目录,请按以下方式将文件名转换为短8.3格式:

FOR %%i IN (%VAR%) DO IF EXIST %%~si\NUL ECHO It's a directory

%%~si转换%%i到一个8.3文件名。要查看您可以使用FOR变量执行的所有其他技巧,请HELP FOR在命令提示符下输入。

(注意-上面给出的示例采用的格式可以在批处理文件中使用。要使其在命令行上正常工作%%,请%在两个地方都用替换为。)


您忘记了我认为的d标志
RomanM

9
不适用于目录符号链接(软链接)或连接点:其路径包含目录链接的文件被误认为目录。要重现,请键入:<Win> cmd <Ctrl> + <Shift> + <Enter> mklink /d LinkDir . <Enter> cd LinkDir<Enter> if exist regedt32.exe\nul echo File erroneously detected as Directory<Enter>rd .
Aaron Thoma

9
没用 但是,在末尾添加反斜杠确实对我有用。例如:如果存在“%〜1 \” echo这是一个目录
MarioVilas 2013年

2
这有效:FOR %% i IN(%1)如果存在%%〜si *,则回声很重
Jakob Sternberg 2014年

2
这也不适用于UNC路径(即\\ server \ share \ ...)。@Vhaerun:请将您的“接受的答案”标记更新为batchman61的标记-这是此页面上唯一可靠的答案
WinTakeAll

95

这有效:

if exist %1\* echo Directory

使用包含空格的目录名称:

C:\>if exist "c:\Program Files\*" echo Directory
Directory

请注意,如果目录包含空格,则必须使用引号:

C:\>if exist c:\Program Files\* echo Directory

也可以表示为:

C:\>SET D="C:\Program Files"
C:\>if exist %D%\* echo Directory
Directory

孩子们,在家可以安全尝试!


5
这似乎很好,甚至可以正确处理空文件夹。更新:似乎也不需要'*',只是最后的'\'似乎足以验证它是一个文件夹。
格兰特·彼得斯

11
真棒,甚至工作目录链接!但是只能用*(也@GrantPeters)
亚伦·托马

7
以防万一引用是一个问题,它也可以工作:如果存在“%〜1 \” echo这是一个目录
MarioVilas 2013年

54

最近由于与上述方法不同而失败。非常确定他们过去曾经工作过,也许与这里的dfs有关。现在使用文件属性并剪切第一个字符

@echo off
SETLOCAL ENABLEEXTENSIONS
set ATTR=%~a1
set DIRATTR=%ATTR:~0,1%
if /I "%DIRATTR%"=="d" echo %1 is a folder
:EOF

12
这完全是最好的答案……如果您没有目标文件或目录的读取权限(这正是我所需要的),它甚至可以工作。谢谢!
ewall

1
此页面上有效的三种解决方案之一:isFile.bat示例:pastebin.com/dmYKKa7M
Jakob Sternberg

12

除了以前的产品,我发现这也行得通:

if exist %1\ echo Directory

不需要%1左右的引号,因为调用者将提供它们。这比我一年前的答案节省了整个按键时间;-)


5
不适用于目录符号链接(软链接)或连接点:其路径包含目录链接的文件被误认为目录。要重现,请键入:<Win> cmd <Ctrl> + <Shift> + <Enter> mklink /d LinkDir . <Enter> cd LinkDir<Enter> if exist regedt32.exe\ echo File erroneously detected as Directory<Enter>rd .
Aaron Thoma 2012年

10

这是一个使用FOR来构建标准路径的脚本,然后将其推送以测试该路径是否为目录。请注意,它如何用于带有空格的路径以及网络路径。

@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

上面存储为“ 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

2
即使目录符号链接(Softlinks)和Junctions也可以使用。(\NUL与“和”技术相对。)
亚伦·托马

1
@accolade-什么是``技巧''
凯文·费根

@KevinFegan(看起来StackExchange更改了`…`内联代码格式的解析。)«»应该是« \»。我指的是在文件名末尾附加反斜杠的做法,如这里建议:stackoverflow.com/questions/138981/...
亚伦托马

6

这完美地工作

if exist "%~1\" echo Directory

我们需要使用%〜1删除%1中的引号,并在末尾添加反斜杠。然后再次将它们全部放入qutes。


3
不适用于目录符号链接(软链接)或连接点:其路径包含目录链接的文件被误认为目录。要重现,请键入:<Win> cmd <Ctrl> + <Shift> + <Enter> mklink /d LinkDir . <Enter> cd LinkDir<Enter> if exist "regedt32.exe\" echo File erroneously detected as Directory<Enter>rd .
Aaron Thoma 2012年

4

@ batchman61方法的一种变体(检查Directory属性)。

这次,我使用外部“查找”命令。

(哦,请注意&&技巧。这是为了避免冗长的IF ERRORLEVEL语法。)

@ECHO OFF
SETLOCAL EnableExtensions
ECHO.%~a1 | find "d" >NUL 2>NUL && (
    ECHO %1 is a directory
)

在以下情况下输出是:

  • 目录。
  • 目录符号链接或结点。
  • 目录符号链接或结点损坏。(不要尝试解析链接。)
  • 您没有读取权限的目录(例如“ C:\ System Volume Information”)

3

NUL技术似乎仅适用于8.3兼容文件名。

(换句话说,“ D:\ Documents and Settings”为“坏”,而“ D:\ DOCUME〜1”为“好”)


我认为当目录名称中有空格(例如“文档和设置”)时,使用“ NUL”技术会有些困难。

我正在使用Windows XP Service Pack 2,并从%SystemRoot%\ system32 \ cmd.exe启动cmd提示符

以下是一些DID不起作用以及对我有用的示例:

(这些都是在交互式提示下“实时”完成的演示。我认为在尝试在脚本中对其进行调试之前,您应该先使它们起作用。)

此DID不起作用:

D:\Documents and Settings>if exist "D:\Documents and Settings\NUL" echo yes

此DID不起作用:

D:\Documents and Settings>if exist D:\Documents and Settings\NUL echo yes

这确实起作用(对我而言):

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

[[看这里!!!!]]
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

这可行,但是有点愚蠢,因为该点已经暗示我在目录中:

D:\Documents and Settings>if exist .\NUL echo yes


1
问题似乎不是长文件名,而是名称中带有空格的目录。或者更确切地说,是变量名周围的引号阻止了NUL技巧的起作用。我在答案中添加了一些代码,可以在测试之前将文件名转换为8.3名称。
戴夫·韦伯

1
该NUL技术不起作用目录的符号链接(软链接)或结:文件被误认为目录的路径包含目录链接。要重现,请键入:<Win> cmd <Ctrl> + <Shift> + <Enter> mklink /d LinkDir . <Enter> cd LinkDir<Enter> if exist regedt32.exe\nul echo File erroneously detected as Directory<Enter>rd .
Aaron Thoma 2012年

3

我用这个:

if not [%1] == [] (
  pushd %~dpn1 2> nul
  if errorlevel == 1 pushd %~dp1
)

3

这可以工作,并且还可以处理其中带有空格的路径:

dir "%DIR%" > NUL 2>&1

if not errorlevel 1 (
    echo Directory exists.
) else (
    echo Directory does not exist.
)

我认为,这可能不是最有效的方法,但比其他解决方案更容易阅读。


1
我最喜欢你的回答。由于某种原因我不明白它突然停止工作,所以我在这里发表了答案。
克里斯·墨菲

另一种选择:如果可以的cd话……当然,请记住您当前的目录,然后set cwd=%cd%再还原...
Frank Nocke 2015年

1
这将验证路径是否存在,但不会区分文件还是文件夹。
dbenham 2015年

3

CD返回一个EXIT_FAILURE在指定目录不存在。并且您获得了条件处理符号,因此您可以像下面这样进行操作。

SET cd_backup=%cd%
(CD "%~1" && CD %cd_backup%) || GOTO Error

:Error
CD %cd_backup%

2

一种非常简单的方法是检查孩子是否存在。

如果一个孩子没有任何孩子,该exist命令将返回false。

IF EXIST %1\. (
  echo %1 is a folder
) else (
  echo %1 is a file
)

如果您没有足够的访问权限(我尚未测试),则可能会有一些误报。


这绝对不能正常工作,请尝试测试:是否存在C:\ Windows \ explorer.exe \。回声是文件夹
indalive

2

如果可以cd进入,它是一个目录:

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%

1

根据本文题为“哪有一个批处理文件测试存在一个目录的”这“并不完全可靠。”

但是我刚刚测试了这个:

@echo off
IF EXIST %1\NUL goto print
ECHO not dir
pause
exit
:print
ECHO It's a directory
pause

它似乎有效


2
阅读文章“不可靠”意味着它在Pathworks,Novell,DR-DOS和OS / 2上失败了,我怀疑对于大多数人来说这将是一个问题。
戴夫·韦伯

因此“并不完全可靠”
RomanM

2
不适用于目录符号链接(软链接)或连接点:其路径包含目录链接的文件被误认为目录。要重现,请键入:<Win> cmd <Ctrl> + <Shift> + <Enter> mklink /d LinkDir . <Enter> cd LinkDir<Enter> if exist "regedt32.exe\NUL" echo File erroneously detected as Directory<Enter>rd .
Aaron Thoma 2012年

1

这是我的解决方案:

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

1

我想发布自己的函数脚本,希望有一天对某人有用。

@pushd %~dp1
@if not exist "%~nx1" (
        popd
        exit /b 0
) else (
        if exist "%~nx1\*" (
                popd
                exit /b 1
        ) else (
                popd
                exit /b 3
        )
)

此批处理脚本检查文件/文件夹是否存在以及它是文件还是文件夹。

用法:

script.bat“路径”

退出代码:

0:文件/文件夹不存在。

1:存在,它是一个文件夹。

3:存在,它是一个文件。


0

在Windows 7和XP下,我无法分辨映射驱动器上的文件与目录。以下脚本:

@回声关闭
如果存在c:\ temp \ data.csv echo data.csv是一个文件
如果存在c:\ temp \ data.csv \ echo data.csv是一个目录
如果存在c:\ temp \ data.csv \ nul echo data.csv是目录
如果存在k:\ temp \ nonexistent.txt echo nonexistent.txt是一个文件
如果存在k:\ temp \ something.txt echo something.txt是一个文件
如果存在k:\ temp \ something.txt \ echo something.txt是一个目录
如果存在k:\ temp \ something.txt \ nul echo something.txt是一个目录

产生:

data.csv是一个文件
something.txt是一个文件
something.txt是一个目录
something.txt是一个目录

因此,请注意,如果您的脚本可能被馈送到了映射路径或UNC路径。以下推式解决方案似乎是最简单的方法。


1
另请参阅@ batchman61中的解决方案,该解决方案通过检查属性来避免此问题。
jdigital 2012年

0

这是我在BATCH文件中使用的代码

```
@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

```


0

这是经过多次测试后(如果存在,推送,dir / AD等)的解决方案。

@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
  • 它适用于没有扩展名的文件
  • 它适用于名为folder.ext的文件夹
  • 它与UNC路径一起使用
  • 它与双引号完整路径一起使用,或者仅与目录名或文件名一起使用。
  • 即使您没有读取权限也可以使用
  • 它适用于目录链接(连接)。
  • 它适用于路径包含目录链接的文件。

0

使用%%~si\NUL方法的一个问题是,它可能会猜错。文件名可能会缩短为错误的文件。我不认为%%~si可以解析8.3文件名,但可以猜测,但是可以使用字符串操作来缩短文件路径。我相信,如果您具有类似的文件路径,则可能无法正常工作。

替代方法:

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

您可以(goto IsFile)||(goto IsDir)用其他批处理命令替换:
(echo Is a File)||(echo is a Directory)


1
不,当然%~s1不会“猜测” /字符串操作短文件名,它会正确解析它。赞dir /x
亚伦·托马

0

如果您的目标是仅处理目录,那么这将很有用。

这取自https://ss64.com/nt/for_d.html

示例...在文件夹C:\ Work \下列出名称以“ User”开头的每个子文件夹:

CD \Work
FOR /D /r %%G in ("User*") DO Echo We found

FOR /D 要么 FOR /D /R

@echo off
cd /d "C:\your directory here"
for /d /r %%A in ("*") do echo We found a folder: %%~nxA
pause

删除/r仅可深入一个文件夹。该/r开关是递归的,在下面的命令中未记录。

for /d来自命令的帮助for /?

FOR / D%variable IN(设置)DO命令[命令参数]

如果set包含通配符,则指定匹配目录名而不是文件名。


1
这是另一个问题的答案。这不适合关于检测给定文件名是否为目录的问题。
jeb

看来这个问题已经死了。这仅允许用户处理目录并跳过检查部分。
科技教育

-3

我们不能只是用这个来测试:

IF [%~x1] == [] ECHO Directory

它似乎为我工作。


这不适用于包含点的文件夹。事实证明,扩展名是猜测,而不是解决。
2014年

如果文件夹名称是myfolder.fld什么?
phuclv
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.