Pregunta

¿Hay alguna forma de averiguar si un archivo es un directorio?

Tengo el nombre del archivo en una variable. En Perl puedo hacer esto:

if(-d $var) { print "it's a directory\n" }
¿Fue útil?

Solución

Puedes hacerlo así:

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

Sin embargo, esto solo funciona para directorios sin espacios en sus nombres. Cuando agrega comillas alrededor de la variable para manejar los espacios, dejará de funcionar. Para manejar directorios con espacios, convierta el nombre del archivo al formato corto 8.3 de la siguiente manera:

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

El %%~si convierte %%i a un nombre de archivo 8.3. Para ver todos los otros trucos que puede realizar con FOR variables, ingrese HELP FOR en el símbolo del sistema.

(Nota: el ejemplo anterior está en el formato para trabajar en un archivo por lotes. Para que funcione en la línea de comando, reemplace el %% con % en ambos lugares.)

Otros consejos

Esto funciona:

if exist %1\* echo Directory

Funciona con nombres de directorio que contienen espacios:

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

Tenga en cuenta que las comillas son necesarias si el directorio contiene espacios:

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

También se puede expresar como:

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

¡Es seguro intentarlo en casa, niños!

Recientemente falló con diferentes enfoques de los anteriores. Muy seguro de que trabajaron en el pasado, tal vez relacionados con dfs aquí. Ahora usando los atributos de los archivos y corte el primer carácter

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

Además de mi oferta anterior, creo que esto también funciona:

if exist %1\ echo Directory

No se necesitan comillas alrededor de% 1 porque la persona que llama las proporcionará. Esto ahorra una pulsación completa sobre mi respuesta de hace un año ;-)

Aquí hay un script que usa FOR para construir una ruta totalmente calificada, y luego se empuja para probar si la ruta es un directorio. Observe cómo funciona para rutas con espacios, así como rutas de red.

@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

Salida de muestra con lo anterior guardado como " 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

Esto funciona perfectamente

if exist "%~1\" echo Directory

necesitamos usar% ~ 1 para eliminar comillas de% 1 y agregar una barra invertida al final. Luego ponga thw entero en qutes nuevamente.

La técnica NUL parece funcionar solo en nombres de archivos compatibles con 8.3.

(En otras palabras, `D: \ Documents and Settings` es " malo " y` D: \ DOCUME ~ 1` es " bueno ")


Creo que hay alguna dificultad al usar " NUL " técnica cuando hay ESPACIOS en el nombre del directorio, como " Documentos y configuraciones. "

Estoy usando el Service Pack 2 de Windows XP e inicio el indicador de cmd desde% SystemRoot% \ system32 \ cmd.exe

Aquí hay algunos ejemplos de lo que NO FUNCIONÓ y lo que FUNCIONÓ para mí:

(Estas son todas las demostraciones realizadas " live " en un mensaje interactivo. Me imagino que debería hacer que las cosas funcionen allí antes de intentar depurarlas en un script.)

Esto NO FUNCIONÓ:

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

Esto NO FUNCIONÓ:

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

Esto sí funciona (para mí):

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

[[Mira aquí mismo !!!! ]]
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

Esto funciona, pero es un poco tonto, porque el punto ya implica que estoy en un directorio:

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

Esto funciona y también maneja rutas con espacios en ellas:

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

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

Probablemente no sea la más eficiente pero más fácil de leer que las otras soluciones en mi opinión.

Una variación del enfoque de @ batchman61 (comprobar el atributo de Directorio).

Esta vez uso un comando externo 'buscar'.

(Ah, y tenga en cuenta el truco &&. Esto es para evitar la larga y aburrida sintaxis IF ERRORLEVEL.)

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

Salidas sí en:

  • Directorios.
  • Directorio de enlaces simbólicos o uniones.
  • Broken enlaces simbólicos de directorio o uniones. (No intenta resolver enlaces).
  • Directorios en los que no tiene permiso de lectura (por ejemplo, " C: \ System Volume Information ")

Yo uso esto:

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

Una forma muy simple es verificar si el niño existe.

Si un hijo no tiene ningún hijo, el comando exist devolverá falso.

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

Puede tener algunos falsos negativos si no tiene el derecho de acceso suficiente (no lo he probado).

Basado en este artículo titulado " ¿Cómo puede un archivo por lotes probar la existencia de un directorio " es " no completamente confiable " ;.

PERO acabo de probar esto:

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

y parece funcionar

Aquí está mi solución:

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 puede cd ingresar en él, es un directorio:

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%

Me gustaría publicar mi propio script de función sobre este tema, espero ser útil para alguien algún día.

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

Este script por lotes verifica si existe un archivo / carpeta y si es un archivo o una carpeta.

Uso :

script.bat " PATH "

Código (s) de salida:

0: el archivo / carpeta no existe.

1: existe y es una carpeta.

3: existe y es un archivo.

CD devuelve un EXIT_FAILURE cuando el directorio especificado no existe. Y obtuvo símbolos de procesamiento condicional , por lo que puede hacer lo siguiente para esto.

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

:Error
CD %cd_backup%

En Windows 7 y XP, no puedo hacer que diga archivos vs. directorios en unidades mapeadas. El siguiente script:

@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

produce:

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

Así que tenga cuidado si su script puede ser alimentado con una ruta asignada o UNC. La solución pushd a continuación parece ser la más infalible.

Este es el código que uso en mis archivos 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 ... el truco 'nul' no funciona si usa comillas en los nombres, lo que representa la mayoría de los archivos con nombres o espacios largos.

Por ejemplo,

if exist "C:\nul" echo Directory

no hace nada, pero

if exist C:\nul echo Directory

funciona.

Finalmente se me ocurrió esto, que parecía funcionar para todos los casos:

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

o si puede asegurar que cumple con todos los requisitos para 'nul', una solución es:

if exist %~sf1\nul echo Directory

Póngalos en un archivo por lotes como 'test.bat' y haga 'test.bat MyFile'.

Aquí está mi solución después de muchas pruebas con 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
  • Funciona con archivos que no tienen extensión
  • Funciona con carpetas llamadas folder.ext
  • Funciona con la ruta UNC
  • Funciona con una ruta completa entre comillas dobles o solo con el nombre de directorio o el nombre de archivo únicamente.
  • Funciona incluso si no tiene permisos de lectura
  • Funciona con Enlaces de Directorio (Uniones).
  • Funciona con archivos cuya ruta contiene un enlace de directorio.

Un problema con el uso del método %%~si\NUL es que existe la posibilidad de que adivine mal. Es posible que un nombre de archivo se acorte al archivo incorrecto. No creo que %%~si resuelva el nombre de archivo 8.3, pero lo adivine, pero usando la manipulación de cadenas para acortar la ruta del archivo. Creo que si tiene rutas de archivo similares, puede que no funcione.

Un método alternativo:

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

Puede reemplazar (goto IsFile)||(goto IsDir) con otros comandos por lotes:
(echo Is a File)||(echo is a Directory)

¿No podemos simplemente probar con esto:

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

Parece que funciona para mí.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top