Як перевірити, чи файл є каталогом у пакетному сценарії?


76

Чи є спосіб дізнатись, чи файл є каталогом?

У мене є ім’я файлу у змінній. У Perl я можу зробити це:

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

Відповіді:


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

2
Це працює: ДО %% i В (% 1) РЕАЛУЙТЕ, ЩО ІСНУЄ %% ~ si * ECHO - ПАПКА
Якоб Штернберг

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
Це, здається, добре, навіть правильно обробляє порожню папку правильно. Оновлення: схоже, також не потрібно знака *, достатньо лише значка \ \ в кінці, щоб підтвердити, що це папка.
Grant Peters

11
Чудово, це працює навіть із посиланнями на каталог ! Але тільки з *!! (Також @GrantPeters)
Аарон Тома

7
Про всяк випадок, коли лапки є проблемою, це теж працює: якщо існує "% ~ 1 \" echo Це каталог
MarioVilas

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
Якоб Штернберг

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

10

Ось сценарій, який використовує 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

2
Це працює навіть із символічними посиланнями (програмними посиланнями) та переходами . (На відміну від \NULі `` прийомів.)
Аарон Тома,

1
@accolade - що таке `` методи?
Кевін Феган

@KevinFegan (Схоже, StackExchange змінив синтаксичний розбір `…`вбудованого форматування коду.) `` '' Мало бути «\ ». Я мав на увазі підхід додавання зворотної скісної риски в кінці імені файлу, наприклад, запропонований тут: stackoverflow.com/questions/138981/…
Аарон Тома

6

Це працює чудово

if exist "%~1\" echo Directory

нам потрібно використовувати% ~ 1, щоб видалити лапки з% 1 і додати зворотну скісну риску в кінці. Потім знову поставте thw цілим у 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

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", коли в назві каталогу є ПРОСТОРИ, наприклад "Документи та налаштування".

Я використовую пакет оновлень 2 для Windows XP і запускаю командний рядок cmd з% SystemRoot% \ system32 \ cmd.exe

Ось кілька прикладів того, що НЕ працювало, і що ПРАЦЮЄ для мене:

(Це всі демонстрації, які виконуються "в прямому ефірі" в інтерактивному підказці. Я вважаю, що вам слід змусити речі працювати там, перш ніж намагатись їх налагодити у сценарії.)

Це НЕ працювало:

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


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

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%відновити пізніше ...
Френк Ноке,

1
Це підтверджує, що шлях існує, але не розрізняє файл або папку.
dbenham


2

Дуже простий спосіб - перевірити, чи існує дитина.

Якщо у дитини немає дитини, existкоманда поверне false.

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

Ви можете мати помилковий негатив, якщо у вас немає достатнього права доступу (я його не перевіряв).


це не працює абсолютно, спробуйте перевірити: якщо існує C: \ Windows \ explorer.exe \. echo is folder
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

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 я не можу змусити його розпізнавати файли та папки на відображених дисках. Наступний сценарій:

@echo вимкнено
якщо існує 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

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

Ось моє рішення після багатьох тестів, якщо існують, 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 шляхом
  • Він працює з повним шляхом із подвійними лапками або лише з іменем / ім'ям файлу.
  • Це працює, навіть якщо у вас немає дозволу на читання
  • Він працює з посиланнями на каталог (Junctions).
  • Він працює з файлами, шлях яких містить посилання на каталог.

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 \, яка має ім'я, що починається на "Користувач":

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% змінна IN (встановити) DO команда [команда-параметри]

Якщо набір містить символи підстановки, тоді вказується відповідність іменам каталогів замість імен файлів.


1
Це відповідь на інше питання. ЦЕ запитання про виявлення не відповідає, якщо дане ім’я файлу є каталогом.
jeb

Вбачаючи, як на це питання відповіли до смерті. Це просто дозволяє користувачеві обробляти каталоги та пропускати частину перевірки.
Ste

-3

Чи не можемо ми просто перевірити це:

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

Здається, це працює для мене.


Це не буде працювати в папках, що містять крапку. Виявляється, розширення вгадується, а не вирішується.
Якоб Штернберг

а якщо назва папки myfolder.fld?
phuclv
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.