15

我需要获取当前正在执行的批处理文件的文件夹名称。我一直在尝试使用以下语法(目前是错误的)循环当前目录:

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

几个问题,我似乎无法将“mydir”变量值作为搜索字符串传递。它似乎只有在我传递命令时才有效;我的语法错误,无法弄清楚原因。

我的想法是用'\'分隔符循环文件夹字符串,但这也会引起问题。如果我在每个循环上设置一个变量,那么最后一个值设置将是当前文件夹名称。例如,给定以下路径:

C:\Folder1\Folder2\Folder3\Archive.bat

我希望解析出值'Folder3'。

我需要解析该值,因为它的名称将是我将在批处理文件中进一步创建的另一个文件夹的一部分。

如果有人可以提供帮助,非常感谢。我可能完全是在叫错树,所以任何其他方法也会受到极大的欢迎。

4

13 回答 13

21

在尝试了其中一些建议后,我发现成功使用了以下 1 班轮(在 windows 2008 中)

for %%a in (!FullPath!) do set LastFolder=%%~nxa
于 2011-01-03T19:08:23.110 回答
10

你非常接近它:) 这应该有效:

@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

由于某种原因 for 命令不喜欢 '\' 作为分隔符,所以我将所有 '\' 转换为 ';' 第一个 ( SET mydir=%mydir:\=;%)

于 2008-11-11T14:47:54.797 回答
6

当我寻找当前目录的最后一段时,我发现了这个旧线程。以前的作家的回答使我得出以下结论:

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

正如前面所解释的,不要忘记在使用 %_LAST_SEGMENT_% 创建的任何路径周围加上引号(就像我在示例中使用 %CD% 所做的那样)。

希望这可以帮助某人...

于 2012-09-24T13:25:40.017 回答
4

这个问题有点老了,但我不止一次地寻找解决方案,所以这是我刚刚整理的一个全新的解决方案。

诀窍是我们采用所需的路径,备份一个级别以创建用于替换的文件夹掩码,然后将文件夹掩码替换为空。

要对其进行测试,只需复制并粘贴到任何目录中的命令脚本 (.cmd) 中,然后运行它。它只会吐出您当前所在的最深目录。

笔记:

  • 将 %~dp0 替换为您喜欢的任何路径(实际上,它将返回运行批处理文件的最深文件夹。这与 %cd% 不同。)
  • 指定 'pathtofind' 变量时,请确保没有引号,例如 c:\some path 而不是 "c​​:\some path"。
  • 文件夹屏蔽的最初想法是我的
  • 路径中的空格没有问题
  • 文件夹深度不是问题
  • 这个批处理脚本技巧的天才使之成为可能http://www.dostips.com/DtCodeBatchFiles.php#Batch.FindAndReplace

希望这对其他人有帮助。

@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
于 2010-07-04T21:40:19.890 回答
2

3行脚本得到结果......

找到了 2 种额外的方法来实现目标,与此问题的其他答案不同,它不需要批处理“功能”,不需要延迟扩展,也没有 Tim Peel 的答案对目录深度的限制:

@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

修订:在我的新修订之后,这是一个示例输出:

Current directory path: Documents#and#Settings,username,.sqldeveloper,tmp,my_folder,MY.again
Current directory name: MY.again
Press any key to continue . . .

这意味着脚本不处理文件夹名称中的“#”或“,”,但可以对其进行调整。

附录:在dostips论坛中询问某人后,找到了一种更简单的方法:

@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
于 2011-11-03T04:08:55.970 回答
2

要返回原始海报的问题:

例如,给定以下路径:C:\Folder1\Folder2\Folder3\Archive.bat 我希望解析出值“Folder3”。

简单的解决方案是:

for /D %%I in ("C:\Folder1\Folder2\Folder3\Archive.bat\..") do echo parentdir=%%~nxI

会给'Folder3'。文件/路径不需要存在。当然,......对于父母的父母目录,或者......对于上面的那个(等等)也可以工作。

于 2012-05-10T14:36:30.733 回答
1

如果任何文件夹的名称中有空格,请稍作改动 - 在操作之前和之后将空格替换为“:”:

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
于 2008-11-11T15:56:56.530 回答
1

伙计们,真是一团糟。这很容易,而且在没有 CD 的情况下在内存中执行此操作会更快。

这将获取路径的最后两个目录。根据需要修改它以获取任何行的最后一个标记。我基于此的原始代码出于我自己的目的而具有更多的复杂性。

仅供参考,这可能不允许带有感叹号的路径,因为我使用的是 enabledelayedexpansion,但这可以修复。

它也不适用于普通驱动器根目录。这可以通过多种方式避免。检查输入路径以什么结尾,或计数器,或修改令牌并检查行为等。

@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
于 2010-10-18T20:04:23.077 回答
1

我修改了@Jonathan给出的答案,因为它在批处理文件中对我不起作用,但下面的这个确实有效,并且还支持其中包含空格的文件夹。:

for %%a in ("%CD%") do set LastFolder=%%~nxa
echo %LastFolder%

这将获取当前目录并回显最后一个最深的文件夹,如下例所示,如果文件夹是这样的:

C:\Users\SuperPDX\OneDrive\Desktop Environment\

批处理代码与此相呼应:桌面环境

于 2019-10-05T07:06:03.343 回答
0

在 FOR 命令的批处理文件中,您需要在 %whatever 前面加上一个额外的 %(例如 %%whatever)。

'echo %~p0' 将打印批处理文件的当前目录。

于 2008-11-11T14:22:10.590 回答
0

这就是我们最终得到的(稍微粗暴一点,只能深入:)

@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%
于 2008-11-11T15:04:23.797 回答
0

我不知道它是否是我正在使用的 Windows 版本(win2k3),但 FOR 循环并没有给我任何有用的信息来尝试遍历单个字符串。根据我的观察(以及 FOR /? 信息),对于 FOR 的每一行输入,您都会获得一次迭代,并且无法将其更改为在一行内进行迭代。您可以为给定的行分成多个标记,但这只是 FOR 循环体的一次调用。

我确实认为这些答案中的 CALL :LABEL 方法做得很好。直到看到这个我才知道是那个“;” 和 "," 都被识别为参数分隔符。因此,一旦将反斜杠替换为分号,就可以调用标签并使用 SHIFT 进行迭代。

因此,根据其他人在这里发布的内容,我有以下解决方案。实际上,我并不想获取最后一个文件夹名称,而是想找到直到某个已知目录名称之前的所有内容。这就是下面实现的内容。

@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
于 2010-06-11T19:10:46.440 回答
-2

不幸的是,这只有在深入一些但在山顶有问题时才能很好地工作......将此程序放入“C:\ Windows”例如将导致......“C:\ Windows” ,不是预期的“Windows”。仍然很棒,并且仍然可以修复损坏。我的做法:

@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

现在它对我来说工作得很好,谢谢你的想法,我一直在寻找类似的东西。

于 2010-08-23T00:54:28.420 回答