Wie teste ich, ob eine Datei ein Verzeichnis in einem Batch-Skript ist?

75

Gibt es eine Möglichkeit herauszufinden, ob eine Datei ein Verzeichnis ist?

Ich habe den Dateinamen in einer Variablen. In Perl kann ich das tun:

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

Antworten:

55

Sie können es so machen:

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

Dies funktioniert jedoch nur für Verzeichnisse ohne Leerzeichen in ihren Namen. Wenn Sie die Variable in Anführungszeichen setzen, um die Leerzeichen zu verarbeiten, funktioniert sie nicht mehr. Um Verzeichnisse mit Leerzeichen zu verarbeiten, konvertieren Sie den Dateinamen wie folgt in das kurze 8.3-Format:

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

Das %%~sikonvertiert %%iin einen 8.3-Dateinamen. Um alle anderen Tricks zu sehen, die Sie mit FORVariablen ausführen können, geben Sie HELP FORan einer Eingabeaufforderung ein.

(Anmerkung - das oben angegebene Beispiel ist in dem Format zur Arbeit in einer Batch - Datei , um es auf der Kommandozeile zu bekommen, tauschen Sie die. %%Mit %an beiden Orten.)

Dave Webb
quelle
Sie haben die d-Flagge vergessen, denke ich
RomanM
9
Dies funktioniert nicht mit verzeichnissymbolischen Links (Softlinks) oder Junctions : Dateien, deren Pfad einen Verzeichnislink enthält, werden fälschlicherweise als Verzeichnis erkannt. cmd Geben mklink /d LinkDir . Sie zum Reproduzieren Folgendes ein: <Win> <Strg> + <Umschalt> + <Eingabe> <Eingabe> cd LinkDir<Eingabe> if exist regedt32.exe\nul echo File erroneously detected as Directory<Eingabe>rd .
Aaron Thoma
9
Es funktioniert nicht. Das Hinzufügen eines Backslash am Ende hat jedoch für mich funktioniert. Zum Beispiel: falls vorhanden "% ~ 1 \" echo Es ist ein Verzeichnis
MarioVilas
2
Dies funktioniert: FOR %% i IN (% 1) DO IF EXIST %% ~ si * ECHO IST ORDNER
Jakob Sternberg
2
Dies funktioniert auch nicht für UNC-Pfade (dh \\ Server \ Freigabe \ ...). @ Vhaerun: Bitte aktualisieren Sie Ihre "akzeptierte Antwort" Markierung auf Batchman61 - das ist die einzige robuste Antwort auf dieser Seite
WinTakeAll
94

Das funktioniert:

if exist %1\* echo Directory

Funktioniert mit Verzeichnisnamen, die Leerzeichen enthalten:

C:\>if exist "c:\Program Files\*" echo Directory
Directory

Beachten Sie, dass die Anführungszeichen erforderlich sind, wenn das Verzeichnis Leerzeichen enthält:

C:\>if exist c:\Program Files\* echo Directory

Kann auch ausgedrückt werden als:

C:\>SET D="C:\Program Files"
C:\>if exist %D%\* echo Directory
Directory

Dies ist sicher zu Hause zu versuchen, Kinder!

Gerard
quelle
4
Dies scheint gut zu sein, es behandelt sogar leere Ordner korrekt. Update: scheint auch nicht das '*' zu erfordern, nur das '\' am Ende scheint zu reichen, um zu überprüfen, ob es sich um einen Ordner handelt.
Grant Peters
10
Super, das funktioniert sogar mit Directory Links ! Aber nur mit dem *!! (Auch @GrantPeters)
Aaron Thoma
6
Nur für den Fall, dass die Anführungszeichen ein Problem sind, funktioniert dies auch: falls vorhanden "% ~ 1 \" echo Es ist ein Verzeichnis
MarioVilas
54

Kürzlich mit anderen Ansätzen als oben gescheitert. Ganz sicher, dass sie in der Vergangenheit gearbeitet haben, vielleicht im Zusammenhang mit dfs hier. Verwenden Sie nun die Dateiattribute und schneiden Sie das erste Zeichen aus

@echo off
SETLOCAL ENABLEEXTENSIONS
set ATTR=%~a1
set DIRATTR=%ATTR:~0,1%
if /I "%DIRATTR%"=="d" echo %1 is a folder
:EOF
batchman61
quelle
12
Dies ist die absolut beste Antwort hier ... Es funktioniert sogar, wenn Sie keine Leseberechtigungen für die Zieldatei oder das Zieldatei haben (genau das, was ich brauchte). Vielen Dank!
Ewall
1
Eine von drei Lösungen auf dieser Seite, die funktioniert: isFile.bat Beispiel: pastebin.com/dmYKKa7M
Jakob Sternberg
12

Nach meinem vorherigen Angebot funktioniert dies auch:

if exist %1\ echo Directory

Es sind keine Anführungszeichen um% 1 erforderlich, da der Anrufer diese bereitstellt. Das spart einen ganzen Tastendruck gegenüber meiner Antwort von vor einem Jahr ;-)

Gerard
quelle
5
Dies funktioniert nicht mit verzeichnissymbolischen Links (Softlinks) oder Junctions : Dateien, deren Pfad einen Verzeichnislink enthält, werden fälschlicherweise als Verzeichnis erkannt. cmd Geben mklink /d LinkDir . Sie zum Reproduzieren Folgendes ein: <Win> <Strg> + <Umschalt> + <Eingabe> <Eingabe> cd LinkDir<Eingabe> if exist regedt32.exe\ echo File erroneously detected as Directory<Eingabe>rd .
Aaron Thoma
10

Hier ist ein Skript, das FOR verwendet, um einen vollständig qualifizierten Pfad zu erstellen, und dann pushd, um zu testen, ob der Pfad ein Verzeichnis ist. Beachten Sie, wie es für Pfade mit Leerzeichen sowie für Netzwerkpfade funktioniert.

@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

Beispielausgabe mit dem oben als "isdir.bat" gespeicherten:

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
indiv
quelle
2
Dies funktioniert auch mit Directory Symbolic Links (Softlinks) und Junctions . (Im Gegensatz zu den \NULund `` Techniken.)
Aaron Thoma
1
@accolade - was sind die `` Techniken?
Kevin Fegan
@ KevinFegan (Es sieht so aus, als hätte StackExchange das Parsen der `…`Inline-Code-Formatierung geändert .) «` `» Sollte « \» sein. Ich bezog mich auf den Ansatz, einen Backslash am Ende des Dateinamens anzuhängen
Aaron Thoma
6

Das funktioniert perfekt

if exist "%~1\" echo Directory

Wir müssen% ~ 1 verwenden, um Anführungszeichen aus% 1 zu entfernen und am Ende einen Backslash hinzuzufügen. Dann das Ganze wieder in Qutes geben.

Aziz
quelle
3
Dies funktioniert nicht mit verzeichnissymbolischen Links (Softlinks) oder Junctions : Dateien, deren Pfad einen Verzeichnislink enthält, werden fälschlicherweise als Verzeichnis erkannt. cmd Geben mklink /d LinkDir . Sie zum Reproduzieren Folgendes ein: <Win> <Strg> + <Umschalt> + <Eingabe> <Eingabe> cd LinkDir<Eingabe> if exist "regedt32.exe\" echo File erroneously detected as Directory<Eingabe>rd .
Aaron Thoma
4

Eine Variation des Ansatzes von @ batchman61 (Überprüfen des Directory-Attributs).

Diesmal benutze ich einen externen 'find'-Befehl.

(Oh, und beachten Sie den &&Trick. Dies dient dazu, die langweilige IF ERRORLEVELSyntax zu vermeiden .)

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

Ausgänge ja ein:

  • Verzeichnisse.
  • Verzeichnissymbolische Links oder Kreuzungen.
  • Symbolische Links oder Junctions im defekten Verzeichnis. (Versucht nicht, Links aufzulösen.)
  • Verzeichnisse, für die Sie keine Leseberechtigung haben (z. B. "C: \ System Volume Information")
Explorer09
quelle
3

Die NUL-Technik scheint nur mit 8.3-kompatiblen Dateinamen zu funktionieren.

(Mit anderen Worten, "D: \ Dokumente und Einstellungen" ist "schlecht" und "D: \ DOCUME ~ 1" ist "gut")


Ich denke, es gibt einige Schwierigkeiten bei der Verwendung der "NUL" -Technik, wenn der Verzeichnisname SPACES enthält, z. B. "Dokumente und Einstellungen".

Ich verwende Windows XP Service Pack 2 und starte die Eingabeaufforderung cmd über% SystemRoot% \ system32 \ cmd.exe

Hier sind einige Beispiele dafür, was NICHT funktioniert hat und was für mich funktioniert:

(Dies sind alles Demonstrationen, die "live" an einer interaktiven Eingabeaufforderung durchgeführt werden. Ich denke, Sie sollten die Dinge dort zum Laufen bringen, bevor Sie versuchen, sie in einem Skript zu debuggen.)

Das hat NICHT funktioniert:

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

Das hat NICHT funktioniert:

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

Das funktioniert (für mich):

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

[[Schau gleich hier !!!! ]]
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

Das funktioniert, aber es ist irgendwie albern, weil der Punkt bereits impliziert, dass ich in einem Verzeichnis bin:

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

pestophag
quelle
1
Das Problem scheint nicht bei langen Dateinamen zu liegen, sondern bei Verzeichnissen mit Leerzeichen in ihren Namen. Oder besser gesagt, es sind die Anführungszeichen um den Variablennamen, die verhindern, dass der NUL-Trick funktioniert. Ich habe meiner Antwort einen Code hinzugefügt, der Dateinamen vor dem Testen in 8.3-Namen konvertiert.
Dave Webb
1
Die NUL-Technik funktioniert nicht mit verzeichnissymbolischen Links (Softlinks) oder Junctions : Dateien, deren Pfad einen Verzeichnislink enthält, werden als Verzeichnis falsch erkannt. cmd Geben mklink /d LinkDir . Sie zum Reproduzieren Folgendes ein: <Win> <Strg> + <Umschalt> + <Eingabe> <Eingabe> cd LinkDir<Eingabe> if exist regedt32.exe\nul echo File erroneously detected as Directory<Eingabe>rd .
Aaron Thoma
3

Ich benutze das:

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

Dies funktioniert und behandelt auch Pfade mit Leerzeichen:

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

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

Wahrscheinlich nicht die effizienteste, aber meiner Meinung nach leichter zu lesen als die anderen Lösungen.

Samuel
quelle
1
Ich mochte Ihre Antwort als die einfachste. Aus irgendeinem Grund verstehe ich nicht, dass es plötzlich nicht mehr funktioniert, also habe ich hier eine Antwort gepostet .
Chris Murphy
Alternative Einstellung: Wenn Sie können cd... erinnern Sie sich natürlich an Ihr aktuelles Verzeichnis set cwd=%cd%, um es später wiederherzustellen ...
Frank Nocke
1
Dadurch wird überprüft, ob der Pfad vorhanden ist, es wird jedoch nicht zwischen einer Datei oder einem Ordner unterschieden.
Dbenham
3

CDGibt ein zurück, EXIT_FAILUREwenn das angegebene Verzeichnis nicht vorhanden ist. Und Sie haben bedingte Verarbeitungssymbole , sodass Sie dies wie folgt tun können.

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

:Error
CD %cd_backup%
Константин Ван
quelle
2

Eine sehr einfache Möglichkeit besteht darin, zu überprüfen, ob das Kind existiert.

Wenn ein Kind kein Kind hat, gibt der existBefehl false zurück.

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

Möglicherweise haben Sie ein falsches Negativ, wenn Sie nicht über ausreichende Zugriffsrechte verfügen (ich habe es nicht getestet).

Cedric
quelle
Dies funktioniert nicht unbedingt. Versuchen Sie zu testen: falls vorhanden C: \ Windows \ explorer.exe \. Echo ist Ordner
indalive
2

Wenn Sie hinein können cd, ist es ein Verzeichnis:

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%
Frank Nocke
quelle
1

Basierend auf diesem Artikel mit dem Titel "Wie kann eine Batch-Datei die Existenz eines Verzeichnisses testen" ist sie "nicht ganz zuverlässig".

ABER ich habe das gerade getestet:

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

und es scheint zu funktionieren

RomanM
quelle
2
Das Lesen des Artikels "unzuverlässig" bedeutet, dass er unter Pathworks, Novell, DR-DOS und OS / 2 fehlgeschlagen ist, was meiner Meinung nach für die meisten Menschen ein Problem sein wird.
Dave Webb
daher "nicht ganz zuverlässig"
RomanM
2
Dies funktioniert nicht mit verzeichnissymbolischen Links (Softlinks) oder Junctions : Dateien, deren Pfad einen Verzeichnislink enthält, werden fälschlicherweise als Verzeichnis erkannt. cmd Geben mklink /d LinkDir . Sie zum Reproduzieren Folgendes ein: <Win> <Strg> + <Umschalt> + <Eingabe> <Eingabe> cd LinkDir<Eingabe> if exist "regedt32.exe\NUL" echo File erroneously detected as Directory<Eingabe>rd .
Aaron Thoma
1

Hier ist meine Lösung:

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
user966939
quelle
1

Ich möchte mein eigenes Funktionsskript zu diesem Thema veröffentlichen, um eines Tages für jemanden nützlich zu sein.

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

Dieses Batch-Skript prüft, ob eine Datei / ein Ordner vorhanden ist und ob es sich um eine Datei oder einen Ordner handelt.

Verwendung:

script.bat "PATH"

Exit-Code (s):

0: Datei / Ordner existiert nicht.

1: existiert und es ist ein Ordner.

3: existiert und es ist eine Datei.

M. Jamal
quelle
0

Unter Windows 7 und XP kann ich keine Dateien oder Verzeichnisse auf zugeordneten Laufwerken erkennen. Das folgende Skript:

@echo aus
falls vorhanden c: \ temp \ data.csv echo data.csv ist eine Datei
falls vorhanden c: \ temp \ data.csv \ echo data.csv ist ein Verzeichnis
falls vorhanden c: \ temp \ data.csv \ nul echo data.csv ist ein Verzeichnis
falls vorhanden k: \ temp \ nonexistent.txt echo nonexistent.txt ist eine Datei
falls vorhanden k: \ temp \ Something.txt echo Something.txt ist eine Datei
falls vorhanden k: \ temp \ Something.txt \ echo Something.txt ist ein Verzeichnis
falls vorhanden k: \ temp \ Something.txt \ nul echo Something.txt ist ein Verzeichnis

produziert:

data.csv ist eine Datei
Something.txt ist eine Datei
Something.txt ist ein Verzeichnis
Something.txt ist ein Verzeichnis

Achten Sie also darauf, ob Ihrem Skript möglicherweise ein zugeordneter oder ein UNC-Pfad zugewiesen wird. Die unten stehende Pushd-Lösung scheint die narrensicherste zu sein.

user117529
quelle
1
Siehe auch die Lösung von @ batchman61, mit der dieses Problem durch Überprüfen der Attribute vermieden wird.
jdigital
0

Dies ist der Code, den ich in meinen BATCH-Dateien verwende

```
@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

`` `

Gialloporpora
quelle
0

Hier ist meine Lösung nach vielen Tests mit if exist, pushd, dir / AD, etc ...

@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
  • Es funktioniert mit Dateien ohne Erweiterung
  • Es funktioniert mit Ordnern mit dem Namen folder.ext
  • Es funktioniert mit UNC-Pfad
  • Es funktioniert mit einem vollständigen Pfad in doppelten Anführungszeichen oder nur mit dem Verzeichnisnamen oder Dateinamen.
  • Es funktioniert auch, wenn Sie keine Leseberechtigung haben
  • Es funktioniert mit Verzeichnisverknüpfungen (Junctions).
  • Es funktioniert mit Dateien, deren Pfad einen Verzeichnislink enthält.
Amr Ali
quelle
0

Ein Problem bei der Verwendung der %%~si\NULMethode besteht darin, dass die Möglichkeit besteht, dass sie falsch vermutet wird. Es ist möglich, dass ein Dateiname auf die falsche Datei verkürzt wird. Ich glaube nicht, dass %%~sider 8.3-Dateiname aufgelöst wird, aber ich vermute es, aber ich benutze String-Manipulation, um den Dateipfad zu verkürzen. Ich glaube, wenn Sie ähnliche Dateipfade haben, funktioniert es möglicherweise nicht.

Eine alternative Methode:

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

Sie können durch (goto IsFile)||(goto IsDir)andere Stapelbefehle ersetzen :
(echo Is a File)||(echo is a Directory)

TechGuy
quelle
1
Nein, %~s1der kurze Dateiname wird natürlich nicht "erraten" / manipuliert, sondern korrekt aufgelöst. Wiedir /x
Aaron Thoma
0

Wenn Sie nur Verzeichnisse verarbeiten möchten, ist dies hilfreich.

Dies ist der https://ss64.com/nt/for_d.html entnommen

Beispiel ... Listen Sie jeden Unterordner unter dem Ordner C: \ Work \ auf, dessen Name mit "Benutzer" beginnt:

CD \Work
FOR /D /r %%G in ("User*") DO Echo We found

FOR /D oder FOR /D /R

@echo off
cd /d "C:\your directory here"
for /d /r %%A in ("*") do echo We found a folder: %%~nxA
pause

Entfernen, /rum nur einen Ordner tief zu gehen. Der /rSchalter ist rekursiv und im folgenden Befehl nicht dokumentiert.

Die for /dHilfe vom Befehl genommenfor /?

FOR / D% Variable IN (gesetzt) ​​DO-Befehl [Befehlsparameter]

Wenn set Platzhalter enthält, wird angegeben, dass mit Verzeichnisnamen anstelle von Dateinamen abgeglichen werden soll.

Ste
quelle
1
Dies ist eine Antwort auf eine andere Frage. Es passt nicht zu DIESER Frage zur Erkennung, ob ein bestimmter Dateiname ein Verzeichnis ist.
Jeb
Da die Frage zu Tode beantwortet wurde. Auf diese Weise kann der Benutzer nur Verzeichnisse verarbeiten und den Prüfungsteil überspringen.
Ste
-3

Können wir nicht einfach damit testen:

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

Es scheint für mich zu funktionieren.

Lucien Baron
quelle
Dies funktioniert nicht bei Ordnern, die einen Punkt enthalten. Es stellt sich heraus, dass die Erweiterung erraten und nicht gelöst wurde.
Jakob Sternberg
Was ist, wenn der Ordnername lautet myfolder.fld?
Phuclv