2008-11-11 16 views
14

Necesito obtener el nombre de la carpeta de un archivo por lotes que se está ejecutando actualmente. He estado tratando de iterar sobre el directorio actual utilizando la siguiente sintaxis (que está mal en la actualidad):Lote de Windows: sobre la cadena de la carpeta y analizar el nombre de la última carpeta

set mydir = %~p0 
for /F "delims=\" %i IN (%mydir%) DO @echo %i 

par de problemas en que me parece que no puede pasar el valor de la variable 'midirectorio' en el que la 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 \ Folder3 \ Archive.bat

yo esperaría para 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.

Respuesta

10

Usted eran bastante cerca de ella :) 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 alguna razón el comando para no le gusta '\' como delimitador, lo que convierte todo '\' a '; ' primero (SET mydir=%mydir:\=;%)

+1

Le gusta '|' como mero delimitador, solo tiene que poner% mydir% entre comillas como en '%% i IN ("% mydir%") ' – ErikE

0

En los archivos de proceso por lotes en el comando FOR, deberá anteponer el% cualquiera con un% extra (por ejemplo, %% lo que sea).

'echo% ~ p0' imprimirá el directorio actual del archivo por lotes.

+0

no, imprime la ruta completa al directorio actual menos la letra de la unidad. – djangofan

+0

@djangofan ¿vas a votar por la semántica? – kenny

+0

Nunca hubiera dado un voto que hubiera resultado en que tu respuesta tuviera un "-1". Pero, por otro lado, al no ser lo que el interlocutor quería, tu respuesta tampoco se merecía un "1". – djangofan

0

Esto es lo que teníamos en el extremo (poco más crudo y sólo puede ir 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% 
1

alteración leve de si alguna de las carpetas tienen espacios en sus nombres - reemplazar el espacio de ':' 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 
+0

Esto no es necesario. Simplemente coloque comillas alrededor de% mydir% en la instrucción for. – ErikE

0

no sé si es la versión de windows estoy en (win2k3), pero el bucle FOR no me da nada útil para tratar para iterar a través de una sola cadena. Según mi observación (y la información de 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 fuera de 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 
4

Esta pregunta es un poco viejo, pero yo he buscado una solución más de una vez así que aquí tiene una forma completamente nueva toma en lo que acabo de poner juntos.

El truco es que tomamos la ruta deseada, retrocedemos 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 comandos (.cmd) en cualquier directorio, luego ejecútelo. Será escupir sólo el directorio más profundo que está actualmente en

Notas:.

  • Reemplazar% ~ dp0 con cualquier camino te gusta (ya que es, volverá el más profundo carpeta del archivo por lotes es ejecutar desde. Esto no es lo mismo que% cd%.)
  • Al especificar la variable 'pathtofind', asegúrese de que no haya citas, por ejemplo c: \ alguna ruta y no "c: \ alguna ruta".
  • La idea original para el enmascaramiento de la carpeta es la mina
  • espacios en la ruta no son un problema
  • profundidad de carpetas no es un problema
  • Esto fue posible por el genio de este consejo de secuencias de comandos por lotes http://www.dostips.com/DtCodeBatchFiles.php#Batch.FindAndReplace

¡Espero que esto ayude a otra persona!

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 
-2

Desafortunadamente, esto es trabajo grande sólo cuando ponga algo de profundidad, pero tienen problemas con estar en la cima de la montaña ... Poniendo en este programa "C: \ Windows" por ejemplo resultará con ... "C: \ Windows", no esperado "Windows". Sigue siendo un gran trabajo, y aún se puede reparar el daño. Mi enfoque:

@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 muy bien para mí ahora, gracias por la idea, yo estaba buscando algo así desde hace algún tiempo.

jeth

+1

Gee, copiar las respuestas de otras personas es un poco hortera. – ErikE

1

Sheesh chicos, 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 arreglarse.

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 
18

Después de luchar con algunas de estas sugerencias, me encontré con un usado con éxito el revestimiento después de 1 (en Windows 2008)

for %%a in (!FullPath!) do set LastFolder=%%~nxa 
+0

Esto funcionó muy bien para mí también. – kindall

+1

Esto falló cuando el nombre del archivo tiene un espacio en él. ¡Agregó comillas dobles! ¡FullPath! para que esto funcione – Rupin

+0

_Sweet_. Gracias.Así es como lo usé 'for/d %% P in (% IndividualProjectsFolder% \ *) do para %% F en (%% P) do 7z a% TempRootFolder% \ ZIPs \ CADblokeCADtoolFor %% ~ nF.zip% IndividualProjectsFolder% \ %% ~ nxF \ '(reducción de rebajas) –

2

3 líneas de escritura obtiene el resultado ...

Se encontraron 2 formas adicionales de lograr el objetivo y, a diferencia de las otras respuestas a esta pregunta, no requiere "funciones" de lote, 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 revsion, aquí es un ejemplo de salida:

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 un nombre de carpeta, pero se puede ajustar para hacerlo

Adición: Después de preguntar a alguien en el foro dostips, encontró una manera 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 
+0

No usé la expansión retrasada ni las "funciones" de proceso por lotes, pero para eso falla en muchos casos, como 'C: \', 'C: \ myPath, with, comma',' C: \ Documents & Settings' y 'C: \ myPath_with_underscores' – jeb

+0

Esos casos marginales que son extremadamente raros en un escenario del mundo real. El tema de subrayado es más común y se puede solucionar fácilmente. Actualizaré mi respuesta para acomodar esa. – djangofan

+2

Debería usar la sintaxis quot en sus instrucciones de configuración, de lo contrario tendría problemas con caracteres especiales como '&'. En lugar de 'SET CDIR =% ~ p0' inténtelo con 'SET' CDIR =% ~ p0" 'y' SET "_CDIR =% CDIR: ~ 1, -1%" ' – jeb

2

Para volver a la edición de su creador original:

Por ejemplo, dada la siguiente ruta: C: \ Folder1 \ Folder2 \ Folder3 \ Archive.bat Esperaría analizar el valor 'Folder3'.

La solución simple para esto 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.

6

Encontré este hilo antiguo cuando buscaba el último segmento del directorio actual. Los escritores anteriores respuestas me llevan a la siguiente:

FOR /D %%I IN ("%CD%") DO SET _LAST_SEGMENT_=%%~nxI 
ECHO Last segment = "%_LAST_SEGMENT_%" 

Como han explicado anterior, no se olvide de poner comillas alrededor de cualquier ruta de crear con _LAST_SEGMENT_%% (al igual que lo hice con% CD% en mi ejemplo)

Espero que esto ayude a alguien ...

Cuestiones relacionadas