如何testing文件是批处理脚本中的目录?

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

我有一个variables的文件名。 在Perl中,我可以这样做:

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

你可以这样做:

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

但是,这只适用于名称中没有空格的目录。 当您将引号添加到variables处理空格时,它将停止工作。 要处理带空格的目录,请按如下所示将文件名转换为简短的8.3格式:

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

%%~si%%i转换为8.3文件名。 要查看可以使用FORvariables执行的所有其他技巧,请在命令提示符处inputHELP FOR

(注意 – 上面给出的例子的格式是在batch file中工作,为了使它在命令行上工作,在两个地方用%replace%% 。)

这工作:

 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 

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

最近以不同的方法从上面失败。 相当肯定他们在过去工作,也许在这里与dfs有关。 现在使用文件属性并剪切第一个字符

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

除了我以前的产品,我觉得这也是有效的:

 if exist %1\ echo Directory 

由于调用者将提供它们,因此不需要%1周围的引号。 这节省了我一年前的答案一个完整的击键;-)

这是一个使用FOR构build完全限定path的脚本,然后pushd来testingpath是否是一个目录。 注意它是如何工作的path与空间,以及networkingpath。

 @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 

这完美的作品

 if exist "%~1\" echo Directory 

我们需要使用%〜1从%1中删除引号,并在末尾添加一个反斜杠。 然后把整个重新组合成queta。

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

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


如果在目录名称中有SPACES,比如“Documents and Settings”,那么使用“NUL”技术会有一些困难。

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

以下是DID不能工作的一些例子,以及对我来说有什么作用:

(这些都是演示在交互式提示符下“实时”完成的,我想你应该先在那里工作,然后才能在脚本中debugging它们。)

这不是工作:

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

这工作,也处理与他们的空间的path:

 dir "%DIR%" > NUL 2>&1 if not errorlevel 1 ( echo Directory exists. ) else ( echo Directory does not exist. ) 

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

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

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

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

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

输出是:

  • 目录。
  • 目录符号链接或路口。
  • 破碎的目录符号链接或路口。 (不尝试parsing链接。)
  • 您没有读取权限的目录(例如“C:\ System Volume Information”)

我使用这个:

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

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

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

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

如果您没有足够的访问权限(我没有testing过),您可能会有一些错误的否定。

根据这篇题为“如何batch filetesting目录的存在” 这篇文章 “不完全可靠”。

但我只是testing了这一点:

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

它似乎工作

这是我的解决scheme:

 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 

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

 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% 

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

 @echoclosures
如果存在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是一个目录

所以要小心,如果您的脚本可能会被映射或UNCpath。 下面推动的解决scheme似乎是最简单的。

这是我在我的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 

“`

好的…如果你在名称中使用引号,那么这个'nul'技巧是行不通的,这个引号占了大多数长文件名或空格的文件。

例如,

 if exist "C:\nul" echo Directory 

什么都不做,但是

 if exist C:\nul echo Directory 

作品。

我终于想出了这个,似乎适用于所有情况:

 for /f %%i in ('DIR /A:D /B %~dp1 ^| findstr /X /c:"%~nx1"') do echo Directory 

或者如果你能确保你满足所有“不”的要求,一个解决scheme是:

 if exist %~sf1\nul echo Directory 

把这些放到batch file中,比如'test.bat',然后做'test.bat MyFile'。

这是我的解决scheme经过多次testing,如果存在,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的文件夹
  • 它适用于UNCpath
  • 它使用双引号完整path或者只使用dirname或filename。
  • 即使您没有读取权限,它也能正常工作
  • 它与目录链接(连接)。
  • 它适用于其path包含目录链接的文件。

使用%%~si\NUL方法的一个问题是有可能猜测错误。 它可能有一个文件名缩短到错误的文件。 我不认为%%~siparsing8.3文件名,但猜测它,但使用string操作来缩短文件path。 我相信如果你有类似的文件path可能无法正常工作。

另一种方法:

 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 

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

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

 @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“PATH”

退出代码:

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

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

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

我们不能只用这个testing:

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

这似乎为我工作。