如何通过CMD从文件路径获取文件夹路径

171

我需要获取包含cmd文件的文件夹路径。 使用%0可以获取文件名,但如何获取文件夹名呢?

c:\temp\test.cmd >> test.cmd

另外,我的当前目录 != 脚本所在的文件夹。


%w - 工作目录 - kirogasa
%w - 工作目录 - undefined
9个回答

349

对于文件夹名称和驱动器,您可以使用:

echo %~dp0

您可以使用不同的修改器来获得更多信息:

%~I         - expands %I removing any surrounding quotes (")
%~fI        - expands %I to a fully qualified path name
%~dI        - expands %I to a drive letter only
%~pI        - expands %I to a path only
%~nI        - expands %I to a file name only
%~xI        - expands %I to a file extension only
%~sI        - expanded path contains short names only
%~aI        - expands %I to file attributes of file
%~tI        - expands %I to date/time of file
%~zI        - expands %I to size of file

The modifiers can be combined to get compound results:
%~dpI       - expands %I to a drive letter and path only
%~nxI       - expands %I to a file name and extension only
%~fsI       - expands %I to a full path name with short names only

这是从提示符中的“for /?”命令复制粘贴的。

相关

前十个DOS批处理提示(是的,DOS批处理...)显示batchparams.bat(源代码链接为gist):

C:\Temp>batchparams.bat c:\windows\notepad.exe
%~1     =      c:\windows\notepad.exe
%~f1     =      c:\WINDOWS\NOTEPAD.EXE
%~d1     =      c:
%~p1     =      \WINDOWS\
%~n1     =      NOTEPAD
%~x1     =      .EXE
%~s1     =      c:\WINDOWS\NOTEPAD.EXE
%~a1     =      --a------
%~t1     =      08/25/2005 01:50 AM
%~z1     =      17920
%~$PATHATH:1     =
%~dp1     =      c:\WINDOWS\
%~nx1     =      NOTEPAD.EXE
%~dp$PATH:1     =      c:\WINDOWS\
%~ftza1     =      --a------ 08/25/2005 01:50 AM 17920 c:\WINDOWS\NOTEPAD.EXE

很好。我需要特定的分数才能修改别人的维基帖吗? - Wadih M.
@Wadih M.:一般有用的链接http://stackoverflow.com/questions/18557/how-does-stackoverflow-work-the-unofficial-faq - jfs
@Wadih M:从上面的链接可以看到:“编辑可编辑的社区'wiki'帖子+750”。 - jfs
所以,如果您想要一个cmd脚本将工作目录设置为脚本的位置:cd /d "%~dp0"(来自stackoverflow.com/questions/4451668 - Nigel Touch
@Wadih M. 这些选项中哪些可以在.reg文件中使用?我经常在.reg文件中看到%1,但是当我尝试使用更多的奇特选项时它们不起作用。 - ubiquibacon
显示剩余2条评论

62

接受的答案很有帮助,但如果您没有使用传递的值,如何从路径中检索文件名并不是立即显而易见的。我能够从这个线程中解决这个问题,但是为了其他人不那么幸运,这就是如何实现的:

@echo off
setlocal enabledelayedexpansion enableextensions

set myPath=C:\Somewhere\Somewhere\SomeFile.txt
call :file_name_from_path result !myPath!
echo %result%
goto :eof

:file_name_from_path <resultVar> <pathVar>
(
    set "%~1=%~nx2"
    exit /b
)

:eof
endlocal

现在可以在任何地方使用:file_name_from_path函数来检索值,而不仅仅是传递参数的情况。如果参数的顺序不能确定或路径未传递到文件中,则此方法会非常有用。


哇,太棒了!所以Windows批处理文件支持在同一文件中使用函数,这太有用了!这个功能从什么时候开始就已经存在了? - Luke
2
我喜欢你可以通过引用(原样)和值(用“!”括起来)两种方式传递变量。 好的,你可能没有“本地”变量和调用堆栈……但是嘿:毕竟这是一个cmd脚本,无论如何都是一个很大的进步;) 我同意,在单个文件中分区比将其分割到几个文件中更方便 :) - Luke
1
我认为 "goto :eof" 应该改为 "goto eof",去掉冒号,因为它已经导致我出现了错误。 - A Khudairy
2
参见:https://ss64.com/nt/syntax-args.html - 仅使用%~dp1获取驱动器和路径。 - Andrew
3
@AKhudairy是正确的:https://ss64.com/nt/goto.html。在冒号加上后,goto会跳过endlocal(以及您之后放置的任何其他内容,如暂停)。此外,如果您的路径中有空格,则需要在`!myPath!`周围添加引号(或将引号作为myPath的一部分)。 - Rick
显示剩余4条评论

10

为了将它们分配给变量,请确保在等号前后不要添加空格:

set filepath=%~dp1
set filename=%~nx1

那么你应该没有问题。


7

如果有人想要另一种方法...

如果它是路径中的最后一个子目录,您可以使用这个一行代码:

cd "c:\directory\subdirectory\filename.exe\..\.." && dir /ad /b /s

这将返回以下结果:
c:\directory\subdirectory

该命令将向前切换到上一个目录。 /ad 仅显示目录 /b 是一种简洁的格式列表 /s 包括所有子目录。这用于获取要打印的目录的完整路径。


它可能针对当前目录起作用,而不是脚本文件所在的目录。 - Mike Chaliy

4

我在循环中遇到了同样的问题,我想要将zip文件提取到相同的目录中,然后再删除zip文件。问题是7z需要输出文件夹,因此我必须获取每个文件的文件夹路径。这是我的解决方案:

FOR /F "usebackq tokens=1" %%i IN (`DIR /S/B *.zip` ) DO (
  7z.exe x %%i -aoa -o%%i\..
) 

%%i代表完整的文件名路径,%ii\..则表示返回父级文件夹。

希望对您有所帮助。


快速而不太规范的代码。我喜欢这样!从没想过你可以使用“..”扩展文件路径,最终得到父文件夹。 - Oliver R.
这个在Win10上对我有效:FOR /R "C:\sourceDir" %I IN (*.gz) DO C:\7-Zip64\7z.exe x "%I" -aou -o%I..\ - aLx13
是的!这样可以绕过只能在%0、%1、%2等上使用%~dp1(等)的问题。 - Artelius

2
如果Wadih提供的答案无法解决您的问题,可以尝试使用echo %CD%命令。请注意保留HTML标签。

不。%CD% 会返回你启动 .cmd 文件时的 当前工作目录,而不是 .cmd 文件本身所在的目录。 - Andreas Fester

0

这是使用一些编辑过的示例 cmd 组合而成的

@Echo off

Echo ********************************************************
Echo *  ZIP Folder Backup using 7Zip                        *
Echo *  Usage: Source Folder, Destination Drive Letter      *
Echo *  Source Folder will be Zipped to Destination\Backups *
Echo ********************************************************
Echo off

set year=%date:~-4,4%
set month=%date:~-10,2%
set day=%date:~-7,2%
set hour=%time:~-11,2%
set hour=%hour: =0%
set min=%time:~-8,2%

SET /P src=Source Folder to Backup: 
SET source=%src%\*
call :file_name_from_path nam %src%
SET /P destination=Backup Drive Letter:
set zipfilename=%nam%.%year%.%month%.%day%.%hour%%min%.zip
set dest="%destination%:\Backups\%zipfilename%"


set AppExePath="%ProgramFiles(x86)%\7-Zip\7z.exe"
if not exist %AppExePath% set AppExePath="%ProgramFiles%\7-Zip\7z.exe"

if not exist %AppExePath% goto notInstalled

echo Backing up %source% to %dest%

%AppExePath% a -r -tzip %dest% %source%

echo %source% backed up to %dest% is complete!

TIMEOUT 5

exit;

:file_name_from_path <resultVar> <pathVar>
(
    set "%~1=%~nx2"
    exit /b
)


:notInstalled

echo Can not find 7-Zip, please install it from:
echo  http://7-zip.org/

:end
PAUSE

0

在我看来,获取文件完整路径最简单但最强大的方法是:

  1. 启动记事本
  2. 复制并粘贴以下文本: @echo %1 | clip 3
  3. 将文件保存为"CopyAsPath.bat"

现在你可以选择:

  1. 将文件拖到该批处理文件上
  2. 将文件复制到“发送到”菜单文件夹中(%USERPROFILE%\AppData\Roaming\Microsoft\Windows\SendTo)

无论您选择选项1还是选项2,一毫秒后,您都可以:

  1. “按Ctrl-V”
  2. 使用“鼠标右键单击->粘贴”

即可将完整的路径和文件名粘贴到任何您想要的地方。

简单、强大,而且不需要使用任何外部 Windows 工具。


0

对于 .bat 文件,您可能想使用以下命令:

title %~f0

将批处理脚本的路径和文件名放入窗口标题栏中。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接