windows - programa - lenguaje batch
Batch Files: enumera todos los archivos en un directorio con rutas relativas (5)
La manera más simple (pero no la más rápida) de iterar un árbol de directorios y enumerar rutas de archivos relativas es usar FORFILES .
forfiles /s /m *.txt /c "cmd /c echo @relpath"
Las rutas relativas se citarán con un encabezado ./
Como en
"./Doc1.txt"
"./subdir/Doc2.txt"
"./subdir/Doc3.txt"
Para eliminar las cotizaciones:
for /f %%A in (''forfiles /s /m *.txt /c "cmd /c echo @relpath"'') do echo %%~A
Para eliminar las comillas y el encabezado ./
:
setlocal disableDelayedExpansion
for /f "delims=" %%A in (''forfiles /s /m *.txt /c "cmd /c echo @relpath"'') do (
set "file=%%~A"
setlocal enableDelayedExpansion
echo !file:~2!
endlocal
)
o sin usar expansión retardada
for /f "tokens=1* delims=/" %%A in (
''forfiles /s /m *.txt /c "cmd /c echo @relpath"''
) do for %%F in (^"%%B) do echo %%~F
Acerca de los archivos Windows Batch: ¿hay alguna manera de enumerar todos los archivos (o todos los de un tipo específico) en un determinado directorio y sus subdirectorios, incluidas las rutas relativas al directorio actual (o de búsqueda) en la lista?
Por ejemplo, si quiero todos los archivos txt en el directorio actual y los subdirectorios con sus rutas completas, puedo hacer
for /r . %%g in (*.txt) do echo %%g >> C:/temp/test.txt
o
dir *.txt /b /s >> C:/temp/test.txt
y obtendré algo así como
C:/test/Doc1.txt
C:/test/subdir/Doc2.txt
C:/test/subdir/Doc3.txt
Si lo hago
for /r . %%g in (*.txt) do echo %%~nxg >> C:/temp/test.txt
Voy a obtener algo como
Doc1.txt
Doc2.txt
Doc3.txt
Pero lo que realmente quiero es:
Doc1.txt
subdir/Doc2.txt
subdir/Doc3.txt
¿Es posible?
Si mi publicación es demasiado confusa: básicamente quiero " Listar archivos recursivamente en la CLI de Linux con una ruta relativa al directorio actual ", solo para Windows.
Por supuesto, puede escribir un algoritmo recursivo en Batch que le dé un control exacto de lo que hace en cada subdirectorio anidado:
@echo off
set mypath=
call :treeProcess
goto :eof
:treeProcess
setlocal
for %%f in (*.txt) do echo %mypath%%%f
for /D %%d in (*) do (
set mypath=%mypath%%%d/
cd %%d
call :treeProcess
cd ..
)
endlocal
exit /b
Simplemente puede obtener la longitud de caracteres del directorio actual y eliminarlos de su lista absoluta
setlocal EnableDelayedExpansion
for /L %%n in (1 1 500) do if "!__cd__:~%%n,1!" neq "" set /a "len=%%n+1"
setlocal DisableDelayedExpansion
for /r . %%g in (*.log) do (
set "absPath=%%g"
setlocal EnableDelayedExpansion
set "relPath=!absPath:~%len%!"
echo(!relPath!
endlocal
)
Esta respuesta no funcionará correctamente con rutas raíz que contengan signos iguales ( =
). (Gracias @dbenham por señalar eso).
EDITADO: se corrigió el problema con las rutas que contenían !
, nuevamente visto por @dbenham (¡gracias!).
Alternativamente al cálculo de la longitud y la extracción de subcadenas, podría utilizar un enfoque diferente:
almacenar la ruta raíz;
borre la ruta raíz de las rutas de archivos.
Aquí está mi intento (que funcionó para mí):
@ECHO OFF
SETLOCAL DisableDelayedExpansion
SET "r=%__CD__%"
FOR /R . %%F IN (*) DO (
SET "p=%%F"
SETLOCAL EnableDelayedExpansion
ECHO(!p:%r%=!
ENDLOCAL
)
La variable r
se asigna con el directorio actual. A menos que el directorio actual sea el directorio raíz de una unidad de disco, no terminará con (Ya no es el caso, ya que el script ahora lee la variable /
, que modificaremos al agregar el carácter.__CD__
, cuyo valor siempre termina con /
(gracias @jeb!), En lugar de CD
.)
En el ciclo, almacenamos la ruta del archivo actual en una variable. Luego damos salida a la variable, eliminando el camino raíz a lo largo del camino.
@echo on>out.txt
@echo off
setlocal enabledelayedexpansion
set "parentfolder=%CD%"
for /r . %%g in (*.*) do (
set "var=%%g"
set var=!var:%parentfolder%=!
echo !var! >> out.txt
)