84

有什么方法可以判断文件是否是目录?

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

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

23 回答 23

104

这有效:

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

孩子们,这在家里尝试是安全的!

于 2009-09-23T14:51:42.477 回答
64

最近用与上述不同的方法失败了。很确定他们过去工作过,可能与此处的 dfs 有关。现在使用文件属性并剪切第一个字符

@echo off
SETLOCAL ENABLEEXTENSIONS
set ATTR=%~a1
set DIRATTR=%ATTR:~0,1%
if /I "%DIRATTR%"=="d" echo %1 is a folder
:EOF
于 2010-09-16T16:35:55.063 回答
60

你可以这样做:

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转换为%%i8.3 文件名。要查看您可以使用FOR变量执行的所有其他技巧,请HELP FOR在命令提示符处输入。

(注意 - 上面给出的示例是在批处理文件中工作的格式。要让它在命令行上工作,请将两个地方的替换为。%%%

于 2008-09-26T12:01:33.553 回答
12

除了我之前的产品,我发现这也有效:

if exist %1\ echo Directory

%1 周围不需要引号,因为调用者会提供它们。与我一年前的回答相比,这节省了一个完整的击键;-)

于 2010-10-02T12:57:13.320 回答
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
于 2008-09-27T16:22:44.477 回答
6

这完美地工作

if exist "%~1\" echo Directory

我们需要使用 %~1 从 %1 中删除引号,并在末尾添加反斜杠。然后再次将thw整体放入qutes中。

于 2011-09-27T10:08:15.753 回答
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”)
于 2015-03-10T05:29:13.360 回答
4

CDEXIT_FAILURE当指定的目录不存在时返回一个。你有条件处理符号,所以你可以像下面这样做。

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

:Error
CD %cd_backup%
于 2018-07-29T10:12:17.063 回答
3

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

(换句话说,`D:\Documents and Settings` 是 "bad" 而 `D:\DOCUME~1` 是 "good")


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

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

以下是一些无效的示例以及对我有效的示例:

(这些都是在交互式提示下“实时”完成的演示。我认为您应该在尝试在脚本中调试它们之前让事情在那里工作。)

这不起作用:

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

这不起作用:

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

于 2008-09-26T16:53:23.930 回答
3

我用这个:

if not [%1] == [] (
  pushd %~dpn1 2> nul
  if errorlevel == 1 pushd %~dp1
)
于 2010-09-08T13:24:22.230 回答
3

这有效并且还处理其中带有空格的路径:

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

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

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

于 2015-02-10T19:13:27.543 回答
2

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

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

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

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

于 2012-07-26T09:41:05.770 回答
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%
于 2015-10-25T12:17:49.733 回答
1

根据这篇题为“批处理文件如何测试目录的存在”的文章,它“不完全可靠”。

但我刚刚测试了这个:

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

它似乎工作

于 2008-09-26T12:01:41.103 回答
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
于 2013-06-07T13:34:31.343 回答
1

我想发布我自己的关于这个主题的函数脚本,希望有一天对某人有用。

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

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

用法:

脚本.bat“路径”

退出代码:

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

1:存在,是文件夹。

3:存在,是文件。

于 2017-09-20T15:38:03.360 回答
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)

于 2010-09-07T22:12:45.277 回答
0

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

@echo 关闭
如果存在 c:\temp\data.csv 回显 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 路径。下面的 pushd 解决方案似乎是最万无一失的。

于 2011-07-12T22:27:03.023 回答
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

```

于 2012-07-12T20:39:58.450 回答
0

这是我经过多次测试后的解决方案,如果存在、pushd、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 路径
  • 它适用于双引号完整路径或仅使用目录名或文件名。
  • 即使您没有读取权限也可以使用
  • 它适用于目录链接(连接)。
  • 它适用于路径包含目录链接的文件。
于 2014-11-24T02:44:09.507 回答
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 (set) DO 命令 [命令参数]

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

于 2020-01-24T12:01:52.053 回答
0

我最近也在寻找这个,并且偶然发现了一个对我有用的解决方案,但我不知道它有什么限制(因为我还没有发现它们)。我相信这个答案本质上与上面 TechGuy 的答案相似,但我想增加另一个层次的可行性。无论哪种方式,我都在将参数扩展为完整的文件路径方面取得了巨大成功,我相信您必须使用setlocal enableextensions它才能正常工作。

使用下面我可以判断文件是目录还是相反。这在很大程度上取决于用户实际需要什么。如果您更喜欢使用搜索errorlevelvs的结构,&&并且||在您的工作中,您当然可以这样做。有时 if 构造 forerrorlevel可以给您更多的灵活性,因为您不必使用GOTO有时会破坏您的环境条件的命令。

@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

使用它,您可以简单地将文件拖放到您正在构建的工具上以解析它们。相反,如果您正在使用其他方式梳理文件结构并且您已经拥有该文件并且没有将它们拖放到批处理文件中,则可以实现以下操作:

@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
于 2021-06-09T15:58:36.247 回答
-3

我们不能只用这个测试:

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

它似乎对我有用。

于 2013-04-15T14:37:25.267 回答