windows 循环文件夹字符串并解析出最后一个文件夹名称
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/280969/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Loop over folder string and parse out last folder name
提问by Tim Peel
I need to grab the folder name of a currently executing batch file. I have been trying to loop over the current directory using the following syntax (which is wrong at present):
我需要获取当前正在执行的批处理文件的文件夹名称。我一直在尝试使用以下语法遍历当前目录(目前是错误的):
set mydir = %~p0
for /F "delims=\" %i IN (%mydir%) DO @echo %i
Couple of issues in that I cannot seem to pass the 'mydir' variable value in as the search string. It only seems to work if I pass in commands; I have the syntax wrong and cannot work out why.
有几个问题,我似乎无法将 'mydir' 变量值作为搜索字符串传入。它似乎只有在我传入命令时才有效;我的语法错误,无法弄清楚原因。
My thinking was to loop over the folder string with a '\' delimiter but this is causing problems too. If I set a variable on each loop then the last value set will be the current folder name. For example, given the following path:
我的想法是用 '\' 分隔符遍历文件夹字符串,但这也会导致问题。如果我在每个循环上设置一个变量,那么最后设置的值将是当前文件夹名称。例如,给定以下路径:
C:\Folder1\Folder2\Folder3\Archive.bat
C:\Folder1\Folder2\Folder3\Archive.bat
I would expect to parse out the value 'Folder3'.
我希望解析出值“Folder3”。
I need to parse that value out as its name will be part of another folder I am going to create further down in the batch file.
我需要解析该值,因为它的名称将是我将在批处理文件中进一步创建的另一个文件夹的一部分。
Many thanks if anyone can help. I may be barking up the wrong tree completely so any other approaches would be greatly received also.
如果有人可以提供帮助,非常感谢。我可能完全在错误的树上吠叫,所以任何其他方法也会受到很大的欢迎。
采纳答案by Patrick Cuff
You were pretty close to it :) This should work:
你非常接近它:) 这应该有效:
@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 some reason the for command doesn't like '\' as a delimiter, so I converted all '\' to ';' first (SET mydir=%mydir:\=;%
)
出于某种原因,for 命令不喜欢 '\' 作为分隔符,所以我将所有的 '\' 转换为 ';' 第一个 ( SET mydir=%mydir:\=;%
)
回答by Jonathan
After struggling with some of these suggestions, I found an successfully used the following 1 liner (in windows 2008)
在尝试了其中的一些建议之后,我发现成功使用了以下 1 个班轮(在 Windows 2008 中)
for %%a in (!FullPath!) do set LastFolder=%%~nxa
回答by Paul Margetts
I found this old thread when I was looking to find the last segment of the current directory. The previous writers answers lead me to the following:
我在寻找当前目录的最后一段时发现了这个旧线程。以前的作者的回答使我得出以下结论:
FOR /D %%I IN ("%CD%") DO SET _LAST_SEGMENT_=%%~nxI
ECHO Last segment = "%_LAST_SEGMENT_%"
As previous have explained, don't forget to put quotes around any paths create with %_LAST_SEGMENT_% (just as I did with %CD% in my example).
如前所述,不要忘记在使用 %_LAST_SEGMENT_% 创建的任何路径周围加上引号(就像我在示例中使用 %CD% 所做的那样)。
Hope this helps someone...
希望这可以帮助某人...
回答by John Dove
This question's a little old, but I've looked for a solution more than once so here's a completely new take on it that I've just put together.
这个问题有点老了,但我不止一次地寻找解决方案,所以这是我刚刚汇总的全新观点。
The trick is that we take the desired path, back up one level to create a folder mask for substitution and then replace the folder mask with nothing.
诀窍是我们采用所需的路径,备份一级以创建用于替换的文件夹掩码,然后将文件夹掩码替换为空。
To test it, simple copy and paste into a command script (.cmd) in any directory, then run it. It will spit out only the deepest directory you're currently in.
要对其进行测试,只需将其复制并粘贴到任何目录中的命令脚本 (.cmd) 中,然后运行它即可。它只会吐出您当前所在的最深目录。
Notes:
笔记:
- Replace %~dp0 with whatever path you like (as it is, it will return the deepest folder the batch file is run from. This is not the same as %cd%.)
- When specifying the 'pathtofind' variable ensure there are no quotes e.g. c:\some path and not "c:\some path".
- The original idea for folder masking is mine
- Spaces in the path are no problem
- Folder depth is not a problem
- It was made possible by the genius of this batch scripting tip http://www.dostips.com/DtCodeBatchFiles.php#Batch.FindAndReplace
- 将 %~dp0 替换为您喜欢的任何路径(实际上,它将返回运行批处理文件的最深文件夹。这与 %cd% 不同。)
- 当指定 'pathtofind' 变量时,确保没有引号,例如 c:\some path 而不是 "c:\some path"。
- 文件夹屏蔽的最初想法是我的
- 路径中的空格没有问题
- 文件夹深度不是问题
- 这个批处理脚本技巧http://www.dostips.com/DtCodeBatchFiles.php#Batch.FindAndReplace的天才使这成为可能
Hope this helps someone else.
希望这对其他人有帮助。
@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
回答by djangofan
3 lines of script gets the result...
3行脚本得到结果......
Found 2 additional ways to accomplish the goal, and unlike the other answers to this question, it requires no batch "functions", no delayed expansion, and also does not have the limitation that Tim Peel's answer has with directory deepness :
找到了 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
REVISION: after my new revsion, here is an example output:
修订:在我的新修订之后,这是一个示例输出:
Current directory path: Documents#and#Settings,username,.sqldeveloper,tmp,my_folder,MY.again
Current directory name: MY.again
Press any key to continue . . .
This means that the script doesn't handle '#' or ',' in a folder name but can be adjusted to do so.
这意味着脚本不处理文件夹名称中的“#”或“,”,但可以进行调整以进行处理。
ADDENDUM: After asking someone in the dostipsforum, found an even easier way to do it:
附录:在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
回答by foo2
To return to the original poster's issue:
回到原始海报的问题:
For example, given the following path: C:\Folder1\Folder2\Folder3\Archive.bat I would expect to parse out the value 'Folder3'.
例如,给定以下路径:C:\Folder1\Folder2\Folder3\Archive.bat 我希望解析出值“Folder3”。
The simple solution for that is:
对此的简单解决方案是:
for /D %%I in ("C:\Folder1\Folder2\Folder3\Archive.bat\..") do echo parentdir=%%~nxI
will give 'Folder3'. The file/path does not need to exist. Of course, .... for the parent's parent dir, or ...... for the one above that (and so on) work too.
将给出“Folder3”。文件/路径不需要存在。当然,......对于父目录的父目录,或者......对于上面的那个(等等)也有效。
回答by Super_PDX
I modified answergiven by @Jonathan, since it did not work for me in a batch file, but this below does work, and also supports folders with spaces in it.:
我修改的答案给出@Jonathan,因为它没有在批处理文件中对我来说有效,但下面这并不工作,同时还支持文件夹,在它的空间:
for %%a in ("%CD%") do set LastFolder=%%~nxa
echo %LastFolder%
This takes the current directory and echoes the last, deepest folder,as in below example, if the folder is this:
这需要当前目录并回显最后一个最深的文件夹,如下例所示,如果文件夹是这样的:
C:\Users\SuperPDX\OneDrive\Desktop Environment\
The batch code echoes this: Desktop Environment
批处理代码与此相呼应:桌面环境
回答by auvixa
Sheesh guys, what a mess. This is pretty easy, and it's faster to do this in memory without CD.
该死的家伙,真是一团糟。这很容易,而且在没有 CD 的情况下在内存中执行此操作会更快。
This gets the last two directories of a path. Modify it as required to get the last tokens of any line. My original code I based this on has more complexity for my own purposes.
这将获取路径的最后两个目录。根据需要修改它以获取任何行的最后一个标记。出于我自己的目的,我基于此的原始代码具有更多的复杂性。
Fyi, this probably doesn't allow paths with exclamation marks since I'm using enabledelayedexpansion, but that could be fixed.
仅供参考,这可能不允许带有感叹号的路径,因为我使用的是 enabledelayedexpansion,但这可以解决。
It also won't work on a plain drive root. This could be averted in a number of ways. Check what the input path ends with, or a counter, or modifying the token and check behaviour, 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
回答by Tim Peel
Slight alteration for if any of the folders have spaces in their names - replace space to ':' before and after operation:
如果任何文件夹的名称中有空格,请稍微更改 - 在操作前后将空格替换为“:”:
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
回答by ahains
I don't know if it's the version of windows I'm on (win2k3), but the FOR loop isn't giving me anything useful for trying to iterate through a single string. According to my observation (and the FOR /? info) you get one iteration for each line of input to FOR, and there is no way to change this to iterate within a line. You can break into multiple tokens for a given line, but it is only one invocation of the FOR loop body.
我不知道它是否是我使用的 Windows 版本(win2k3),但是 FOR 循环没有给我任何有用的东西来尝试遍历单个字符串。根据我的观察(以及 FOR /? 信息),对于 FOR 的每一行输入,您都会得到一次迭代,并且无法将其更改为在一行内进行迭代。对于给定的行,您可以分解为多个标记,但这只是对 FOR 循环体的一次调用。
I do think the CALL :LABEL approach in these answers does a great job. Something I didn't know until looking at this was that ";" and "," are both recognized as argument separators. So once you replace backslashes with semicolons, you can call your label and iterate through with SHIFT.
我确实认为这些答案中的 CALL :LABEL 方法做得很好。直到看到这个我才知道是“;” 和“,”都被识别为参数分隔符。因此,一旦用分号替换反斜杠,就可以调用标签并使用 SHIFT 进行迭代。
So working off of what is posted by others here, I have the below solution. Instead of grabbing the last folder name, I actually wanted to find everything up until some known directory name.. this is what is implemented below.
因此,根据其他人在这里发布的内容,我有以下解决方案。而不是抓取最后一个文件夹名称,我实际上想找到直到某个已知目录名称为止的所有内容..这就是下面实现的内容。
@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