كيفية اختبار ما إذا كان الملف عبارة عن دليل في برنامج نصي دفعي؟

StackOverflow https://stackoverflow.com/questions/138981

سؤال

هل هناك أي طريقة لمعرفة ما إذا كان الملف هو دليل؟

لدي اسم الملف في متغير.في بيرل يمكنني القيام بذلك:

if(-d $var) { print "it's a directory\n" }
هل كانت مفيدة؟

المحلول

يمكنك القيام بذلك على النحو التالي:

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 في موجه الأوامر.

(ملاحظة - المثال الوارد أعلاه بتنسيق يعمل في ملف دفعي.لتشغيله على سطر الأوامر، استبدل %% مع % في كلا المكانين .)

نصائح أخرى

هذا يعمل:

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 لإنشاء مسار مؤهل بالكامل، ثم يدفع لاختبار ما إذا كان المسار هو دليل.لاحظ كيف يعمل مع المسارات ذات المسافات، بالإضافة إلى مسارات الشبكة.

@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 وإضافة شرطة مائلة عكسية في النهاية.ثم ضع الكل في علامات الاقتباس مرة أخرى.

يبدو أن تقنية NUL تعمل فقط على أسماء الملفات المتوافقة مع الإصدار 8.3.

(وبعبارة أخرى، `D:\Documents and Settings` هو "سيء" و`D:\DOCUME~1` هو "جيد")


أعتقد أن هناك بعض الصعوبة في استخدام تقنية "NUL" عند وجود مسافات في اسم الدليل، مثل "المستندات والإعدادات".

أنا أستخدم حزمة الخدمة Windows XP 2 وأقوم بتشغيل موجه 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

يعمل هذا ويتعامل أيضًا مع المسارات التي تحتوي على مسافات:

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

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

ربما ليس الأكثر كفاءة ولكن أسهل في القراءة من الحلول الأخرى في رأيي.

شكل مختلف من نهج @batchman61 (التحقق من سمة الدليل).

هذه المرة أستخدم أمر "بحث" خارجي.

(أوه، ولاحظ && حيلة.وهذا لتجنب الملل الطويل IF ERRORLEVEL بناء الجملة.)

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

المخرجات نعم على:

  • الدلائل.
  • دليل الروابط أو الوصلات الرمزية.
  • مكسور دليل الروابط أو الوصلات الرمزية.(لا تحاول حل الروابط.)
  • الأدلة التي ليس لديك إذن بقراءتها (على سبيل المثال.""C:\System معلومات وحدة التخزين")

انا استعمل هذا:

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

هناك طريقة بسيطة جدًا وهي التحقق من وجود الطفل.

إذا لم يكن لدى الطفل أي طفل، فإن exist سيعود الأمر خطأ.

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

قد يكون لديك بعض النتائج السلبية الكاذبة إذا لم يكن لديك حق الوصول الكافي (لم أختبره).

مرتكز على هذا المقال بعنوان "كيف يمكن لملف دفعي اختبار وجود دليل" إنه "غير موثوق به تمامًا".

لكنني اختبرت هذا للتو:

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

ويبدو أنه يعمل

هذا هو الحل الخاص بي:

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

إذا استطعت 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%

أرغب في نشر البرنامج النصي الخاص بي حول هذا الموضوع وآمل أن يكون مفيدًا لشخص ما في يوم من الأيام.

@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:موجود، وهو ملف.

CD يعود EXIT_FAILURE عندما يكون الدليل المحدد غير موجود.وحصلت رموز المعالجة الشرطية, ، لذا يمكنك القيام بما يلي لهذا الغرض.

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

:Error
CD %cd_backup%

في نظامي التشغيل Windows 7 وXP، لا يمكنني جعله يخبر الملفات مقابل ملفات.dirs على محركات الأقراص المعينة.البرنامج النصي التالي:

@echo off
if exist c:\temp\data.csv echo data.csv is a file
if exist c:\temp\data.csv\ echo data.csv is a directory
if exist c:\temp\data.csv\nul echo data.csv is a directory
if exist k:\temp\nonexistent.txt echo nonexistent.txt is a file
if exist k:\temp\something.txt echo something.txt is a file
if exist k:\temp\something.txt\ echo something.txt is a directory
if exist k:\temp\something.txt\nul echo something.txt is a directory

ينتج عنه:

data.csv is a file
something.txt is a file
something.txt is a directory
something.txt is a directory

لذا احذر إذا كان من الممكن تغذية البرنامج النصي الخاص بك بمسار معين أو مسار UNC.يبدو أن الحل Pushd أدناه هو الأكثر مضمونة.

هذا هو الرمز الذي أستخدمه في ملفات 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

أو إذا كان بإمكانك التأكد من استيفاء جميع متطلبات "nul" فالحل هو:

if exist %~sf1\nul echo Directory

ضعها في ملف دفعي مثل 'test.bat' وقم بإجراء 'test.bat MyFile'.

هذا هو الحل بعد العديد من الاختبارات مع إذا كان موجودًا، أو 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
  • إنه يعمل مع المسار الكامل ذي علامات الاقتباس المزدوجة أو مع اسم الملف أو اسم الملف فقط.
  • إنه يعمل حتى لو لم يكن لديك أذونات القراءة
  • إنه يعمل مع روابط الدليل (الوصلات).
  • إنه يعمل مع الملفات التي يحتوي مسارها على رابط الدليل.

مشكلة واحدة مع استخدام %%~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)

لا يمكننا فقط اختبار مع هذا:

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

ويبدو أن العمل بالنسبة لي.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top