web-dev-qa-db-fra.com

Comment tester si un fichier est un répertoire dans un script batch?

Est-il possible de savoir si un fichier est un répertoire?

J'ai le nom du fichier dans une variable. En Perl, je peux faire ceci:

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

Vous pouvez le faire comme ça:

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

Toutefois, cela ne fonctionne que pour les répertoires sans espaces dans leurs noms. Lorsque vous ajoutez des guillemets autour de la variable pour gérer les espaces, celle-ci cesse de fonctionner. Pour gérer les répertoires avec des espaces, convertissez le nom du fichier au format 8.3 court comme suit:

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

Le %%~si convertit %%i en un nom de fichier 8.3. Pour voir toutes les autres astuces que vous pouvez effectuer avec les variables FOR, entrez HELP FOR à l'invite de commande.

(Remarque - l'exemple donné ci-dessus est conçu pour fonctionner dans un fichier de commandes. Pour le faire fonctionner en ligne de commande, remplacez %% par % aux deux endroits.)

46
Dave Webb

Cela marche:

if exist %1\* echo Directory

Fonctionne avec les noms de répertoire contenant des espaces:

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

Notez que les guillemets sont nécessaires si le répertoire contient des espaces:

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

Peut aussi être exprimé comme:

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

C'est sûr d'essayer à la maison, les enfants!

78
Gerard

Récemment échoué avec des approches différentes de celles mentionnées ci-dessus. Bien sûr, ils ont travaillé dans le passé, peut-être lié à DFS ici. Maintenant, en utilisant les attributs files et coupez le premier caractère

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

Suite à mon offre précédente, je trouve que cela fonctionne également:

if exist %1\ echo Directory

Il ne faut pas de guillemets autour de% 1 car l'appelant les fournira . Cela évite toute une frappe sur ma réponse il y a un an ;-)

12
Gerard

Voici un script qui utilise FOR pour créer un chemin complet, puis pushd pour vérifier si le chemin est un répertoire. Remarquez comment cela fonctionne pour les chemins contenant des espaces, ainsi que les chemins réseau.

@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

Exemple de sortie avec l’enregistrement ci-dessus enregistré sous le nom "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
9
indiv

Cela fonctionne parfaitement

if exist "%~1\" echo Directory

nous devons utiliser% ~ 1 pour supprimer les guillemets de% 1 et ajouter une barre oblique inverse à la fin. Puis mettez-le à nouveau en entier.

6
Aziz

Une variante de l'approche de @ batchman61 (vérification de l'attribut Annuaire).

Cette fois, j'utilise une commande externe 'find'.

(Oh, et notez l'astuce &&. C'est pour éviter la syntaxe fastidieuse de IF ERRORLEVEL.)

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

Sorties oui sur:

  • Répertoires.
  • Répertoire des liens symboliques ou des jonctions.
  • Cassé répertoire des liens symboliques ou des jonctions. (N'essaye pas de résoudre les liens.)
  • Répertoires sur lesquels vous n’avez pas d’autorisation de lecture (par exemple, "C:\System Volume Information")
3
Explorer09

Cela fonctionne et gère également les chemins contenant des espaces:

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

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

Probablement pas la plus efficace mais plus facile à lire que les autres solutions à mon avis.

3
Samuel

La technique NUL semble ne fonctionner que sur les noms de fichiers conformes à la norme 8.3.

(En d'autres termes, `D:\Documents and Settings` est" mauvais "et` D:\DOCUME ~ 1` est "bon")


Je pense qu'il est difficile d'utiliser la technique "NUL" lorsqu'il y a des espaces dans le nom du répertoire, tels que "documents et paramètres".

J'utilise Windows XP service pack 2 et lance l'invite cmd à partir de% SystemRoot%\system32\cmd.exe.

Voici quelques exemples de ce que DID NE fonctionne PAS et de ce qui fonctionne pour moi:

(Ce sont toutes des démonstrations effectuées "en direct" dans une invite interactive. Je suppose que vous devriez faire en sorte que les choses fonctionnent avant d'essayer de les déboguer dans un script.)

This DID NOT work:

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

This DID NOT work:

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

Cela fonctionne (pour moi):

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

[[Regardez juste ici !!!! ]]
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

Cela fonctionne, mais c'est un peu idiot, car le point implique déjà que je suis dans un répertoire:

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

3
pestophagous

Un moyen très simple est de vérifier si l'enfant existe.

Si un enfant n'a pas d'enfant, la commande exist renverra false.

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

Vous pouvez avoir un faux négatif si vous n’avez pas le droit d’accès suffisant (je ne l’ai pas testé).

2
Cedric

J'utilise ceci:

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

J'aimerais publier mon propre script de fonction sur ce sujet dans l'espoir d'être utile pour quelqu'un un jour.

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

Ce script batch vérifie si le fichier/dossier existe et s'il s'agit d'un fichier ou d'un dossier.

Utilisation:

script.bat "CHEMIN"

Code (s) de sortie:

0: le fichier/dossier n'existe pas.

1: existe et c'est un dossier.

3: existe et c'est un fichier.

1
M. Jamal

Voici ma solution:

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
user966939

CD renvoie un EXIT_FAILURE lorsque le répertoire spécifié n'existe pas. Et vous avez des symboles de traitement conditionnel , vous pouvez donc faire comme ci-dessous pour cela.

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

:Error
CD %cd_backup%

Si vous pouvez y ajouter cd, il s'agit d'un répertoire:

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
Frank Nocke

Basé sur cet article intitulé "Comment un fichier de commandes peut-il vérifier l’existence d’un répertoire", c’est "pas entièrement fiable".

MAIS je viens de tester ceci:

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

et cela semble fonctionner

1
Roman M

Voici ma solution après de nombreux tests avec 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
  • Cela fonctionne avec des fichiers sans extension
  • Cela fonctionne avec les dossiers nommés folder.ext
  • Cela fonctionne avec le chemin UNC
  • Cela fonctionne avec le chemin complet entre guillemets ou avec seulement le nom ou le nom du fichier.
  • Cela fonctionne même si vous n'avez pas les permissions de lecture
  • Cela fonctionne avec les liens de répertoire (jonctions).
  • Il fonctionne avec les fichiers dont le chemin contient un lien de répertoire.
0
Amr Ali

Un problème lié à l’utilisation de la méthode %%~si\NUL est qu’il est possible qu’elle devine mal. Il est possible d'avoir un nom de fichier raccourci vers le mauvais fichier. Je ne pense pas que %%~si résolve le nom de fichier 8.3, mais le devine, mais utilisez une manipulation de chaîne pour raccourcir le chemin du fichier. Je crois que si vous avez des chemins de fichiers similaires, cela peut ne pas fonctionner.

Une méthode alternative:

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

Vous pouvez remplacer (goto IsFile)||(goto IsDir) par d'autres commandes batch:
(echo Is a File)||(echo is a Directory)

0
TechGuy

Sous Windows 7 et XP, je ne peux pas le faire dire des fichiers ou des répertoires sur des lecteurs mappés. Le script suivant:

 @ echo off 
 s'il existe c:\temp\data.csv echo data.csv est un fichier 
 s'il existe c:\temp\data.csv\echo data.csv est un répertoire 
 s'il existe c:\temp\data.csv\nul echo data.csv est un répertoire 
 s'il existe k:\temp\nonexistent.txt echo nonexistent.txt est un fichier .__ s'il existe k:\temp\quelque chose .txt echo quelque chose.txt est un fichier 
 s'il existe k:\temp\quelque chose.txt\echo quelque chose.txt est un répertoire 
 s'il existe k:\temp\quelque chose.txt\nul echo quelque chose.txt est un répertoire 

produit:

 data.csv est un fichier 
 quelque chose.txt est un fichier 
 quelque chose.txt est un répertoire 
 quelque chose.txt est un répertoire 

Alors méfiez-vous si votre script peut être alimenté par un chemin mappé ou UNC. La solution pushd ci-dessous semble être la plus infaillible.

0
user117529

Ok ... l'astuce "nulle" ne fonctionne pas si vous utilisez des guillemets dans les noms, ce qui représente la plupart des fichiers avec des noms de fichiers longs ou des espaces.

Par exemple,

if exist "C:\nul" echo Directory

ne fait rien, mais

if exist C:\nul echo Directory

travaux.

J'ai finalement trouvé cela, qui semblait fonctionner pour tous les cas:

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

ou si vous pouvez vous assurer que vous répondez à toutes les exigences pour «nul», la solution est la suivante:

if exist %~sf1\nul echo Directory

Mettez-les dans un fichier de commandes comme "test.bat" et faites "test.bat MonFichier".

0
DrBB

C'est le code que j'utilise dans mes fichiers 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
gialloporpora