Как проверить, является ли путь файлом или каталогом в пакетном файле Windows?

Я искал здесь, нашел кого-то с помощью этого

set is_dir=0
for %%i in ("%~1") do if exist "%%~si"\nul set is_dir=1

но не сработало, когда %1==c:\this is a file with spaces.csproj, тест все еще успешен, что означает, что он все еще будет рассматриваться как папка!!!

Кто-нибудь знает ответ, я думаю, это очень распространенная проблема, и Windows существует уже много-много лет, у нее должно быть очень простое решение....

7 ответов

Решение

Я знаю if exist path\nul тест для папки, используемой для работы на MS-DOS. Я не знаю, было ли это сломано с введением длинных имен файлов.

я знал это if exist "long path\nul" не работает в пакетном режиме Windows. До сегодняшнего дня я не осознавал, что if exist path\nul работает на Vista и выше, пока путь в короткой форме 8.3.

Оригинальный код работает на Vista. Кажется, что он должен работать и на XP, но я считаю, что мешает следующая ошибка XP: Пакетный параметр%~s1 дает неверное короткое имя 8.3.

Исходный код не нуждается в цикле FOR, он может просто использовать %~s1

Вот вариант, который полностью классифицирует путь как INVALID, FILE или FOLDER. Он работает на Vista, но не работает на XP из-за %~s1 ошибка. Я не уверен, как это работает на MS-DOS.
РЕДАКТИРОВАТЬ 2015-12-08: Есть ряд ситуаций Windows, где это не удается

@echo off
if not exist "%~1" ( set "type=INVALID" ) else if exist %~s1\nul ( set "type=FOLDER" ) else ( set "type=FILE" )
@echo "%~1" = %type%

Я считаю, что этот вариант будет работать практически со всеми версиями пакета Microsoft, включая MS-DOS и XP. (очевидно, он не будет работать на ранних версиях DOS, которые не поддерживают PUSHD)

@echo off
if exist "%~1" (2>nul pushd "%~1" && (popd&set "type=FOLDER") || set "type=FILE" ) else set "type=INVALID"
echo "%~1" = %type%

ОБНОВЛЕНИЕ 2014-12-26

Я уверен, что следующее будет работать на всех версиях Windows начиная с XP, но я тестировал только на Win 7.
Редактировать 2015-12-08: Это может произойти сбой на сетевых дисках, потому что тест папки может ложно сообщить о файле как о папке

@echo off
if exist %1\ (
  echo %1 is a folder
) else if exist %1 (
  echo %1 is a file
) else (
  echo %1 does not exist
)

ОБНОВЛЕНИЕ 2015-12-08

Наконец - тест, который действительно должен работать на любой версии Windows начиная с XP, в том числе с сетевыми дисками и путями UNC

for /f "tokens=1,2 delims=d" %%A in ("-%~a1") do if "%%B" neq "" (
  echo %1 is a folder
) else if "%%A" neq "-" (
  echo %1 is a file
) else (
  echo %1 does not exist
)

Я просто попробовал таким образом. Надеюсь это поможет.

@ECHO OFF
SET CURR_DIR=%CD%
SET IS_DIR=0
CD %1% 
IF "%ERRORLEVEL%"=="0" SET IS_DIR=1
CD %CURR_DIR%
ECHO IS DIRECTORY %IS_DIR% 

Выход:

D:\Work\Stand alone Java classes>test.bat D:\Work\Training
IS DIRECTORY 1

D:\Work\Stand alone Java classes>test.bat D:\Work\Training\SRT.txt
The directory name is invalid.
IS DIRECTORY 0

Параметр /ad для команды "dir" выводит список папок, параметр /b для пустых. Предполагая, что у вас есть проверки на наличие файла, используйте:

dir /ad /b ChangeThisToYourFilename 1> NUL 2> NUL
if %ERRORLEVEL% EQU 0 (
    echo is a file
) else (
    echo is NOT a file
)

Это решение объединяет расширение параметра атрибута файла (%~a1) с извлечением переменной подстроки (%variable:~0,1%):

@ECHO OFF

CALL :is_directory C:\Windows
CALL :is_directory C:\MinGW\share\doc\mingw-get\README
CALL :is_directory C:\$Recycle.Bin
CALL :is_directory "C:\Documents and Settings"
CALL :is_directory "%LOGONSERVER%\C$\Users\All Users"

GOTO :EOF

:is_directory
    SETLOCAL
    SET file_attribute=%~a1
    IF "%file_attribute:~0,1%"=="d" (
        ECHO %file_attribute% %1 is a directory
    ) ELSE (
        ECHO %file_attribute% %1 is NOT a directory
    )
    ENDLOCAL
    GOTO :EOF

Выход:

d-------- C:\Windows is a directory
--a------ C:\MinGW\share\doc\mingw-get\README is NOT a directory
d--hs---- C:\$Recycle.Bin is a directory
d--hs---l "C:\Documents and Settings" is a directory
d--hs---l "\\MYCOMPUTER\C$\Users\All Users" is a directory

Для 1 вкладыша:

dir /a:d /b C:\Windows 2>&1 | findstr /i /n /c:"File Not Found">nul && (@echo. Im a file) || (@echo. Im a folder)

например, изменить C:\Windows в C:\Windows\Notepad.exe

-Извините, Арун, Дбенхэм, не читал вашу! Такой же как..

Ранее я использовал "\nul" метод, но долгое время я использовал "\*" проверить, является ли существующая спецификация файла папкой или файлом. Насколько я знаю, он работает на всех версиях Windows, от Windows 95 (и, возможно, более ранних версий) до всех текущих версий Windows.

Итак, как и в случае с другими методами, сначала проверьте, существует ли файл. Затем, чтобы увидеть, является ли это папкой, протестируйте ее с помощью: if exist "%fspec%\*":

if not exist "%fspec%"   goto :NotExistOrInvalid

rem "%fspec%" is "Valid" and is either a "Folder", or a "File".
if     exist "%fspec%\*" goto :IsValidAndIsAFolder

rem "%fspec%" is a "File" (a "Regular File" or a Shortcut/Link).
goto :IsValidAndIsAFile

Например:

set "fspec=XYZ:%perlpath%"
if not exist "%fspec%" echo "%fspec%": Invalid or not found && rem Invalid, goto :NotExistOrInvalid

set "fspec=%perlpath%"
if not exist "%fspec%" echo "%fspec%": Invalid or not found && rem goto :NotExistOrInvalid

rem "%fspec%" Is a "Valid" filespec and is either a "Folder", or a "File".
if exist "%fspec%\*" (echo "%fspec%" is a "Folder".) else echo "%fspec%" is a "File".

set "fspec=%perlpath%\perl.exe"
if not exist "%fspec%" echo "%fspec%": Invalid or not found && rem Invalid, goto :NotExistOrInvalid

rem "%fspec%" Is a "Valid" filespec and is either a "Folder", or a "File".
if exist "%fspec%\*" (echo "%fspec%" is a "Folder".) else echo "%fspec%" is a "File".

Выход для этого:

"XYZ:F:\usr\perl\bin": Invalid or not found
"F:\usr\perl\bin" is a "Folder".
"F:\usr\perl\bin\perl.exe" is a "File".

Я думаю, что не хватает определения функции в официальной документации, на самом деле я ожидаю, что базовая встроенная функция cmd.exe должна вернуться, если файл или папка с указанным именем существует в сценарии, однако разделение файла и папки цель более высокой функции рычага, например, dir... следовательно, эти требования могут быть выполнены с помощью других средств, очень многих... в моем случае сейчас, в 2023 году, я заканчиваю папки, например, в \;

      @echo off
IF EXIST %OneDriveCommercial%\desktop\ (
    copy "%appdata%\Microsoft\Windows\Start Menu\Programs\Work Resources (RADC)\*.lnk" "%OneDriveCommercial%\desktop\"
    echo Copied RDAC to %OneDriveCommercial%\desktop
) else (
    copy "%appdata%\Microsoft\Windows\Start Menu\Programs\Work Resources (RADC)\*.lnk" "%userprofile%\desktop"
    echo Copied RDAC to %userprofile%\desktop
)
Другие вопросы по тегам