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

93

是否有办法查找一个文件是否是目录?

我有一个存储在变量中的文件名,在Perl中,我可以这样做:

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

23个回答

110

这个有效:

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
看起来很好,它甚至可以正确处理空文件夹。更新:似乎不需要 '*',只需在结尾处加 '' 就足以验证它是一个文件夹。 - Grant Peters
13
太棒了,这甚至可以与目录链接一起使用!但只有在使用*时才有效!!(还要@GrantPeters) - Aaron Thoma
7
如果引号有问题,可以尝试这个:如果存在 "%~1" 目录,则显示 It's a directory。 - MarioVilas
1
这种方法在Windows 10 20H2中不起作用。 - CoolCmd
太好了!即使是使用UNC路径和映射到网络共享的驱动器字母,它也适用于我。以前我只使用 \ ,这对本地文件和目录有效。 - GravityWell
显示剩余2条评论

73

最近尝试了以上不同的方法但都失败了。相信它们过去是有效的,也许与这里的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示例:http://pastebin.com/dmYKKa7M - Jakob Sternberg
1
不知道为什么,但我的批处理文件无法将%1扩展到文件/文件夹的完整路径。我必须使用%~f1。它会将像...这样的路径扩展为实际路径。 - WesternGun
这是最好的方法,因为它使用了文档功能,所以将来的Windows版本中也能正常工作。例如,此页面上获得最多“赞”的方法在Windows 10 20H2中不起作用。但是这个方法可以。 - CoolCmd

61

您可以这样做:

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

(注意-上面给出的示例是为批处理文件格式而设计的。要在命令行上运行它,请在两个位置将 %% 替换为 %。)


10
这不适用于目录符号链接(软链接)或联接:路径中包含目录链接的文件会被错误地识别为目录。要复制,请输入:<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" 则输出“这是一个目录”。 - MarioVilas
MarioVilas是正确的。至少在Windows 7上,"\NUL"不起作用,但只有 "" 起作用!谢谢! - Dss
2
这个可以运行:FOR %%i IN (%1) DO IF EXIST %%~si* ECHO IS FOLDER - Jakob Sternberg
2
这对于UNC路径也不起作用(即\server\share...)。@Vhaerun:请将您的“已接受答案”标记更新为batchman61的答案 - 这是此页面上唯一健壮的答案。 - WinTakeAll
显示剩余4条评论

12

继我的先前回答之后,我发现这也可以正常工作:

if exist %1\ echo Directory

不需要在%1周围加引号,因为调用者会提供它们。这比我一年前的答案节省了一个按键;-)


7
使用目录符号链接(软链接)或联接将导致THIS DOES NOT WORK:路径包含目录链接的文件会被错误地识别为目录。要复现,请输入:<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

11

这是一个使用FOR循环构建完全限定路径的脚本,然后使用pushd来测试路径是否为目录。请注意它如何处理带有空格以及网络路径的路径。

@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

3
即使涉及到目录符号链接(软链接)和联接,这也能正常工作。(与\NUL\技术相反。) - Aaron Thoma
1
@accolade - 什么是“技术”? - Kevin Fegan
1
@KevinFegan(看起来StackExchange更改了\…``行内代码格式的解析方式。) « »本应该是«`` »。 我指的是在文件名末尾添加反斜杠的方法,例如在此处提出的建议:https://dev59.com/unVC5IYBdhLWcg3w9F89#143935?noredirect=1#answer-3845794 - Aaron Thoma

6

这完美地运行。

if exist "%~1\" echo Directory

我们需要使用%~1来去除%1中的引号,并在末尾添加反斜杠。然后再将整个内容放入引号中。

4
使用目录符号链接(软链接)或Junctions时,THIS DOES NOT WORK:路径中包含目录符号链接的文件被错误地识别为目录。要重现此问题,请输入:<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

4

CD命令在指定的目录不存在时返回EXIT_FAILURE。如果您使用条件处理符号,您可以像下面这样进行操作。

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

:Error
CD %cd_backup%

4

这是@batchman61方法的变体(检查目录属性)。

这次我使用了外部的“find”命令。

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

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

对以下情况输出yes:

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

3

这个功能可以处理路径中带有空格的情况:

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

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

在我看来,这可能不是最高效的解决方案,但比其他解决方案更易读。


1
我喜欢你的答案,因为它是最简单的。但出于某些原因,我不明白它为什么突然停止工作,所以我在这里发布了一个答案(https://dev59.com/V2kw5IYBdhLWcg3wMHoY#31095955)。 - Chris Murphy
另一种方法是:如果你可以使用 cd 命令进入该目录... 当然,在执行该命令之前,记得先保存当前目录,以便稍后恢复... - Frank N
2
这个函数验证路径是否存在,但无法区分文件和文件夹。 - dbenham
这个建议对我不起作用。要修复它,请使用dir "%DIR%" /A:D > NUL 2>&1来使得dir在处理文件时退出错误代码不等于0。 - Michael Podlejska

3
我使用这个:
if not [%1] == [] (
  pushd %~dpn1 2> nul
  if errorlevel == 1 pushd %~dp1
)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接