循环文件夹字符串并解析出最后一个文件夹名称

时间:2008-11-11 14:07:45

标签: windows batch-file cmd

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

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

其中的几个问题我似乎无法将'mydir'变量值作为搜索字符串传递。如果我传入命令,它似乎只能起作用;我的语法错误,无法解决原因。

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

  

C:\ Folder1中\ FOLDER2 \ Folder3 \ Archive.bat

我希望解析出'Folder3'这个值。

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

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

13 个答案:

答案 0 :(得分:19)

在努力解决其中一些建议后,我发现成功使用了以下1个衬垫(在Windows 2008中)

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

答案 1 :(得分: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:\=;%

答案 2 :(得分:6)

当我想找到当前目录的最后一段时,我找到了这个旧线程。 以前的作者回答引导我到以下几点:

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

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

希望这有助于某人...

答案 3 :(得分:4)

这个问题有点陈旧,但我不止一次寻找解决方案,所以这里是我刚刚放在一起的一个全新的解决方案。

诀窍是我们采用所需的路径,备份一个级别来创建用于替换的文件夹掩码,然后用任何内容替换文件夹掩码。

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

注意:

  • 将%~dp0替换为您喜欢的任何路径(实际上,它将返回运行批处理文件的最深文件夹。这与%cd%不同。)
  • 指定'pathtofind'变量时,请确保没有引号,例如c:\某个路径而不是“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

答案 4 :(得分:2)

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

找到了另外两种方法来实现这个目标,与此问题的其他答案不同,它不需要批量“功能”,没有延迟扩展,也没有Tim Peel的答案与目录深度的限制:< / p>

@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 . . .

这意味着脚本不会在文件夹名称中处理“#”或“,”,但可以进行调整以执行此操作。

ADDENDUM:在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

答案 5 :(得分:2)

返回原始海报的问题:

  

例如,给定以下路径:   C:\ Folder1中\文件夹2 \ Folder3 \ Archive.bat   我希望解析出'Folder3'这个值。

简单的解决方案是:

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

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

答案 6 :(得分: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

答案 7 :(得分:1)

Sheesh伙计们,真是一团糟。这非常简单,在没有CD的情况下在内存中执行此操作会更快。

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

Fyi,这可能不允许带有惊叹号的路径,因为我正在使用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

答案 8 :(得分:1)

我修改了https://codesandbox.io/s/angular-qdq4f给出的answer,因为它在批处理文件中对我不起作用,但是下面的方法可以工作,并且还支持其中包含空格的文件夹。

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

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

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

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

答案 9 :(得分:0)

在FOR命令的批处理文件中,您需要在%之前添加%(例如%%)。

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

答案 10 :(得分: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%

答案 11 :(得分:0)

我不知道它是否是我所使用的Windows版本(win2k3),但FOR循环并没有给我任何有用的尝试迭代单个字符串。 根据我的观察(以及FOR /?info),您可以为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

答案 12 :(得分:-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

现在它对我来说效果很好,感谢这个想法,我一段时间都在寻找类似的东西。