subdirectorios - Lote de Windows: repite la cadena de la carpeta y analiza el nombre de la última carpeta
tag files and folders (12)
Esto es lo que tuvimos al final (un poco más crudo y solo puede llegar tan profundo :)
@echo off
for /f "tokens=1-10 delims=/" %%A in (''echo %~p0'') do (
if NOT .%%A==. set new=%%A
if NOT .%%B==. set new=%%B
if NOT .%%C==. set new=%%C
if NOT .%%D==. set new=%%D
if NOT .%%E==. set new=%%E
if NOT .%%F==. set new=%%F
if NOT .%%G==. set new=%%G
if NOT .%%H==. set new=%%H
if NOT .%%I==. set new=%%I
if NOT .%%J==. set new=%%J
)
@echo %new%
Necesito tomar el nombre de la carpeta de un archivo por lotes actualmente en ejecución. He estado intentando recorrer el directorio actual usando la siguiente sintaxis (que en este momento está mal):
set mydir = %~p0
for /F "delims=/" %i IN (%mydir%) DO @echo %i
Un par de problemas en los que parece que no puedo pasar el valor de la variable ''mydir'' como cadena de búsqueda. Parece funcionar solo si paso comandos; Tengo la sintaxis incorrecta y no puedo entender por qué.
Mi idea era recorrer la cadena de carpetas con un delimitador ''/', pero esto también está causando problemas. Si configuro una variable en cada ciclo, el último conjunto de valores será el nombre de la carpeta actual. Por ejemplo, dada la siguiente ruta:
C: / Carpeta1 / Carpeta2 / Carpeta3 / Archivo.bat
Esperaría analizar el valor ''Folder3''.
Necesito analizar ese valor ya que su nombre será parte de otra carpeta que voy a crear más abajo en el archivo por lotes.
Muchas gracias si alguien puede ayudar. Puedo estar ladrando el árbol equivocado por completo por lo que cualquier otro enfoque sería muy recibido también.
Leve alteración para si alguna de las carpetas tiene espacios en sus nombres - reemplace el espacio a '':'' antes y después de la operación:
set mydir="%~p0"
set mydir=%mydir:/=;%
set mydir=%mydir: =:%
for /F "tokens=* delims=;" %%i IN (%mydir%) DO call :LAST_FOLDER %%i
goto :EOF
:LAST_FOLDER
if "%1"=="" (
set LAST=%LAST::= %
goto :EOF
)
set LAST=%1
SHIFT
goto :LAST_FOLDER
En los archivos de proceso por lotes en el comando FOR, deberá anteponer% cualquiera que tenga un% extra (por ejemplo, %% lo que sea).
''echo% ~ p0'' imprimirá el directorio actual del archivo por lotes.
Estabas muy cerca de esto :) Esto debería funcionar:
@echo OFF
set mydir="%~p0"
SET mydir=%mydir:/=;%
for /F "tokens=* delims=;" %%i IN (%mydir%) DO call :LAST_FOLDER %%i
goto :EOF
:LAST_FOLDER
if "%1"=="" (
@echo %LAST%
goto :EOF
)
set LAST=%1
SHIFT
goto :LAST_FOLDER
Por algún motivo, al comando for no le gusta ''/' como delimitador, así que convertí todo ''/' a '';'' primero ( SET mydir=%mydir:/=;%
)
No sé si es la versión de Windows en la que estoy (win2k3), pero el bucle FOR no me proporciona nada útil para tratar de iterar a través de una sola cadena. De acuerdo con mi observación (y la información FOR /?) Obtienes una iteración por cada línea de entrada a FOR, y no hay forma de cambiar esto para iterar dentro de una línea. Puede dividirse en varios tokens para una línea determinada, pero es solo una invocación del cuerpo de bucle FOR.
Creo que el enfoque CALL: LABEL en estas respuestas hace un gran trabajo. Algo que no sabía hasta que miré esto fue ese ";" y "," son reconocidos como separadores de argumentos. Entonces, una vez que reemplazas las barras invertidas con punto y coma, puedes llamar a tu etiqueta e iterar con SHIFT.
Así que trabajando sobre lo publicado por otros aquí, tengo la siguiente solución. En lugar de tomar el último nombre de la carpeta, en realidad quería encontrar todo hasta algún nombre de directorio conocido ... esto es lo que se implementa a continuación.
@echo off
if "%1"=="" goto :USAGE
set FULLPATH=%~f1
set STOPDIR=%2
set PATHROOT=
:: Replace backslashes with semicolons
set FULLPATH=%FULLPATH:/=;%
:: Iterate through path (the semicolons cause each dir name to be a new argument)
call :LOOP %FULLPATH%
goto :EOF
:LOOP
::Exit loop if reached the end of the path, or the stop dir
if "%1"=="" (goto :EOF)
if "%1"=="%STOPDIR%" (goto :EOF)
::If this is the first segment of the path, set value directly. Else append.
if not defined PATHROOT (set PATHROOT=%1) else (set PATHROOT=%PATHROOT%/%1)
::shift the arguments - the next path segment becomes %i
SHIFT
goto :LOOP
:USAGE
echo Usage:
echo %~0 ^<full path to parse^> ^<dir name to stop at^>
echo E.g. for a command:
echo %~0 c:/root1/child1/child2 child2
echo The value of c:/root1/child1 would be assigned to env variable PATHROOT
Esta pregunta es un poco vieja, pero he buscado una solución más de una vez, así que aquí te presento una idea completamente nueva que acabo de armar.
El truco es que tomamos la ruta deseada, realizamos una copia de seguridad de un nivel para crear una máscara de carpeta para la sustitución y luego reemplazamos la máscara de la carpeta con nada.
Para probarlo, simplemente copie y pegue en un script de comando (.cmd) en cualquier directorio, luego ejecútelo. Escupirá solo el directorio más profundo en el que te encuentras actualmente.
Notas:
- Reemplace% ~ dp0 con la ruta que desee (tal como está, devolverá la carpeta más profunda desde la que se ejecuta el archivo por lotes. Esto no es lo mismo que% cd%).
- Al especificar la variable ''pathtofind'', asegúrese de que no haya comillas, por ejemplo, c: / alguna ruta y no "c: / alguna ruta".
- La idea original para enmascarar carpetas es mía
- Los espacios en el camino no son un problema
- La profundidad de la carpeta no es un problema
- Fue posible gracias al genio de esta sugerencia de scripts por lotes http://www.dostips.com/DtCodeBatchFiles.php#Batch.FindAndReplace
¡Espero que esto ayude a alguien más!
Gracias,
John D
@echo off
set pathtofind=%~dp0
if not exist %pathtofind% echo Path does not exist&pause>nul&goto :eof
cd /d %pathtofind%
set path1=%cd%
cd ..
set path2=%cd%
call set "path3=%%path1:%path2%/=%%"
echo %path3%
pause>nul
Desafortunadamente, esto está funcionando muy bien solo cuando se pone algo de profundidad pero tiene problemas para estar en la cima de la montaña ... Poner este programa en "C: / Windows", por ejemplo, resultará en ... "C: / Windows" , no se esperaba "Windows". Sigue siendo un gran trabajo, y aún se puede reparar el daño. Mi acercamiento:
@echo off
set pathtofind=%~dp0
if not exist %pathtofind% echo Path does not exist&pause>nul&goto :eof
cd /d %pathtofind%
set path1=%cd%
cd ..
set path2=%cd%
set path4=%~dp1
call set "path3=%%path1:%path2%/=%%"
call set "path5=%%path3:%path4%*/=%%"
echo %path5%
pause>nul
Y está funcionando bien para mí ahora, gracias por la idea, estaba buscando algo así por un tiempo.
jeth
Chicos Sheesh, qué desastre. Esto es bastante fácil, y es más rápido hacer esto en la memoria sin CD.
Esto obtiene los dos últimos directorios de una ruta. Modifíquelo según sea necesario para obtener los últimos tokens de cualquier línea. Mi código original en el que basé esto tiene más complejidad para mis propios fines.
Fyi, esto probablemente no permite caminos con signos de exclamación ya que estoy usando enabledelayedexpansion, pero eso podría ser arreglado.
Tampoco funcionará en una raíz de unidad simple. Esto podría evitarse de varias maneras. Verifique con qué finaliza la ruta de entrada, o un contador, o modificando el token y verificando el comportamiento, etc.
@echo off&setlocal enableextensions,enabledelayedexpansion
call :l_truncpath "C:/Windows/temp"
----------
:l_truncpath
set "_pathtail=%~1"
:l_truncpathloop
for /f "delims=/ tokens=1*" %%x in ("!_pathtail!") do (
if "%%y"=="" (
set "_result=!_path!/!_pathtail!"
echo:!_result!
exit/b
)
set "_path=%%x"
set "_pathtail=%%y"
)
goto l_truncpathloop
Después de luchar con algunas de estas sugerencias, encontré un trazador de líneas 1 utilizado con éxito (en Windows 2008)
for %%a in (!FullPath!) do set LastFolder=%%~nxa
3 líneas de script obtienen el resultado ...
Se encontraron 2 formas adicionales de lograr el objetivo y, a diferencia de las otras respuestas a esta pregunta, no requiere "funciones" por lotes, no hay expansión retardada y tampoco tiene la limitación que la respuesta de Tim Peel tiene con la profundidad del directorio:
@echo off
SET CDIR=%~p0
SET CDIR=%CDIR:~1,-1%
SET CDIR=%CDIR:/=,%
SET CDIR=%CDIR: =#%
FOR %%a IN (%CDIR%) DO SET "CNAME=%%a"
ECHO Current directory path: %CDIR%
SET CNAME=%CNAME:#= %
ECHO Current directory name: %CNAME%
pause
REVISIÓN: después de mi nueva revisión, aquí hay un resultado de ejemplo:
Current directory path: Documents#and#Settings,username,.sqldeveloper,tmp,my_folder,MY.again
Current directory name: MY.again
Press any key to continue . . .
Esto significa que el script no maneja ''#'' o '','' en el nombre de una carpeta, pero se puede ajustar para hacerlo.
ADDENDUM: Después de preguntarle a alguien en el foro dostips , encontró una manera aún más fácil de hacerlo:
@echo off
SET "CDIR=%~dp0"
:: for loop requires removing trailing backslash from %~dp0 output
SET "CDIR=%CDIR:~0,-1%"
FOR %%i IN ("%CDIR%") DO SET "PARENTFOLDERNAME=%%~nxi"
ECHO Parent folder: %PARENTFOLDERNAME%
ECHO Full path: %~dp0
pause>nul
Para volver al tema del cartel original:
Por ejemplo, dada la siguiente ruta: C: / Folder1 / Folder2 / Folder3 / Archive.bat Esperaría analizar el valor ''Folder3''.
La solución simple para eso es:
for /D %%I in ("C:/Folder1/Folder2/Folder3/Archive.bat/..") do echo parentdir=%%~nxI
dará ''Folder3''. El archivo / ruta no necesita existir. Por supuesto, ... para el padre padre del padre, o ...... para el anterior que (y así sucesivamente) también funciona.
Encontré este hilo viejo cuando buscaba el último segmento del directorio actual. Las respuestas de los escritores anteriores me llevan a lo siguiente:
FOR /D %%I IN ("%CD%") DO SET _LAST_SEGMENT_=%%~nxI
ECHO Last segment = "%_LAST_SEGMENT_%"
Como se explicó anteriormente, no olvide poner comillas alrededor de las rutas de acceso creadas con% _LAST_SEGMENT_% (tal como lo hice con% CD% en mi ejemplo).
Espero que esto ayude a alguien...