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

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

J’ai le nom de fichier dans une variable. En Perl, je peux le faire:

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

Vous pouvez le faire comme ça:

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

Cependant, 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, elle cessera de fonctionner. Pour gérer les répertoires avec des espaces, convertissez le nom de 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 réaliser avec les variables FOR , entrez HELP FOR à une invite de commandes.

(Remarque: l’exemple ci-dessus est dans le format pour fonctionner dans un fichier de commandes. Pour le faire fonctionner sur la ligne de commande, remplacez le %% par % dans les deux endroits.)

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!

Récemment échoué avec différentes approches de ce qui précède. Bien sûr, ils ont travaillé dans le passé, peut-être lié à DFS ici. Maintenant, utilisez les atsortingbuts de fichiers 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 

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

 if exist %1\ echo Directory 

Aucune citation autour de% 1 n’est nécessaire car l’appelant les fournira. Cela permet d’économiser une frappe complète sur ma réponse d’il y a un an 😉

Voici un script qui utilise FOR pour créer un chemin complet, puis pushd pour tester si le chemin est un répertoire. Remarquez comment cela fonctionne pour les chemins avec 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 ce qui précède enregistré sous “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 

Cela fonctionne parfaitement

 if exist "%~1\" echo Directory 

Nous devons utiliser% ~ 1 pour supprimer les guillemets de% 1 et append une barre oblique inverse à la fin. Ensuite, placez le tout en qutes à nouveau.

La technique NUL semble fonctionner uniquement sur les noms de fichiers compatibles 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” quand il y a des ESPACES dans le nom du répertoire, tels que “Documents and Settings”.

J’utilise le Service Pack 2 de Windows XP et lancez l’invite cmd à partir de% SystemRoot% \ system32 \ cmd.exe

Voici quelques exemples de ce qui n’a pas fonctionné et de ce qui fonctionne pour moi:

(Ce sont toutes les démonstrations faites “en direct” à une invite interactive. Je pense que vous devriez faire en sorte que les choses fonctionnent avant d’essayer de les déboguer dans un script.)

Cela n’a pas fonctionné:

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

Cela n’a pas fonctionné:

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

2008
09/25/2008 05:14 PM 200809~1.25 2008.09.25
09/23/2008 03:44 PM 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 cygwin

[[Regardez juste ici !!!! ]]
09/25/2008 08:34 AM

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

NATION~1 National Instruments Downloads
10/12/2007 11:25 AM NVIDIA
05/13/2008 09:42 AM Office10
09/19/2008 11:08 AM PROGRA~1 Program Files
12/02/1999 02:54 PM 24,576 setx.exe
09/15/2008 11:19 AM TEMP
02/14/2008 12:26 PM tmp
01/21/2008 07:05 PM VXIPNP
09/23/2008 12:15 PM WINDOWS
02/21/2008 03:49 PM wx28
02/29/2008 01:47 PM 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 bête, car le point implique déjà que je suis dans un répertoire:

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

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

 dir "%DIR%" > NUL 2>&1 if not errorlevel 1 ( echo Directory exists. ) else ( echo Directory does not exist. ) 

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

Une variante de l’approche de @ batchman61 (vérification de l’atsortingbut Directory).

Cette fois, j’utilise une commande externe “find”.

(Oh, et notez l’astuce && . Cela évite la longue syntaxe IF ERRORLEVEL .)

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

Sorties oui sur:

  • Répertoires
  • Liens symboliques ou jonctions d’annuaire.
  • Liens symboliques ou jonctions d’annuaire cassés . (N’essaie pas de résoudre les liens)
  • Répertoires sur lesquels vous n’avez pas de permission de lecture (par exemple “C: \ System Volume Information”)

J’utilise ceci:

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

Un moyen très simple consiste à 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 des faux négatifs si vous ne disposez pas d’un droit d’access suffisant (je ne l’ai pas testé).

Basé sur cet article intitulé “Comment un fichier de lot peut-il tester l’existence d’un répertoire” ce n’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

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 

Si vous pouvez y entrer, c’est 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% 

Je voudrais poster mon propre script de fonction sur ce sujet espère ê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.

Usage:

script.bat “PATH”

Code (s) de sortie:

0: fichier / dossier n’existe pas.

1: existe et c’est un dossier.

3: existe et c’est un fichier.

Sous Windows 7 et XP, je ne peux pas le faire lire les fichiers par rapport aux répertoires sur les lecteurs mappés. Le script suivant:

 @Écho 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 \ something.txt echo something.txt est un fichier
 s'il existe k: \ temp \ something.txt \ echo something.txt est un répertoire
 s'il existe k: \ temp \ something.txt \ nul echo something.txt est un répertoire

produit:

 data.csv est un fichier
 quelquechose.txt est un fichier
 quelquechose.txt est un répertoire
 quelquechose.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.

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 

“ `

Ok … le truc “nul” 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é ceci, qui semblait fonctionner dans 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 de «nul», une solution est:

 if exist %~sf1\nul echo Directory 

Mettez-les dans un fichier de commandes comme “test.bat” et faites “test.bat MyFile”.

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

Un problème avec l’utilisation de la méthode %%~si\NUL est qu’il y a une chance que cela devienne faux. Il est possible d’avoir un nom de fichier raccourci au mauvais fichier. Je ne pense pas que %%~si résout le nom de fichier 8.3, mais le devine, mais en utilisant la manipulation de chaîne pour raccourcir le chemin du fichier. Je pense que si vous avez des chemins de fichiers similaires, cela pourrait 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)

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% 

Ne pouvons-nous pas simplement tester avec ceci:

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

Il semble fonctionner pour moi.