【问题标题】:Can a Windows batch file determine its own file name?Windows 批处理文件可以确定自己的文件名吗?
【发布时间】:2012-02-06 13:15:21
【问题描述】:

Windows 批处理文件能否确定自己的文件名?

例如,如果我运行批处理文件 C:\Temp\myScript.bat,在 myScript.bat 中是否有可以确定字符串“myScript.bat”的命令?

【问题讨论】:

标签: windows batch-file cmd


【解决方案1】:

是的。

使用特殊的%0 变量来获取当前文件的路径。

%~n0 只获取不带扩展名的文件名。

%~n0%~x0 获取文件名和扩展名。

也可以写%~nx0来获取文件名和扩展名。

【讨论】:

  • 这是不准确的。 %0 和 %~n0 都只得到文件名部分。 @djangofan 的回答是正确的。
  • %0 返回文件的调用方式。如果使用了完整路径,%0 将拥有该路径。如果你先cd 进入目录并从那里执行批处理,%0 通常不会有路径信息(但在这种情况下你可以从 %cd% 获得)
  • @gogowitsch:你确定吗?我不认为这是真的。
  • 在 Win2012 上,%cd% 将返回调用批处理文件的进程的当前目录。所以,如果你在D:\dir1的提示符下输入Y:\foo\bar.bat,如果bar.bat@echo %cd%,那么它将输出D:\dir1
【解决方案2】:

您可以获取文件名,但也可以获取完整路径,具体取决于您在“%~”和“0”之间放置的内容。任君挑选

d -- drive
p -- path
n -- file name
x -- extension
f -- full path

例如,从 c:\tmp\foo.bat 内部,%~nx0 给你“foo.bat”,而%~dpnx0 给你“c:\tmp\foo.bat”。请注意,这些片段总是按规范顺序组装的,所以如果你变得可爱并尝试%~xnpd0,你仍然会得到“c:\tmp\foo.bat”

【讨论】:

  • 在您的代码块中,您声明 f 是文件名,但在您的示例中,您使用 n 作为文件名。经过一番测试,似乎f是完整路径,n是文件名。
  • @druciferre,我根据你的评论编辑了答案
  • “如果你变可爱了,试试%~xnpd0”...我爱你。
【解决方案3】:

使用以下脚本,根据 SLaks 的回答,我确定正确的答案是:

echo The name of this file is: %~n0%~x0
echo The name of this file is: %~nx0

这是我的测试脚本:

@echo off
echo %0
echo %~0
echo %n0
echo %x0
echo %~n0
echo %dp0
echo %~dp0
pause

我觉得有趣的是 %nx0 不起作用,因为我们知道 '~' 字符通常用于去除/修剪变量的引号。

【讨论】:

    【解决方案4】:

    请记住,0 是批处理文件中参数编号的一种特殊情况,其中0 表示此文件在命令行中给出

    因此,如果文件是 myfile.bat,您可以通过以下几种方式调用它,每种方式都会为您提供与 %0%~0 用法的不同输出:

    myfile

    myfile.bat

    mydir\myfile.bat

    c:\mydir\myfile.bat

    "c:\mydir\myfile.bat"

    如果您从正确的相对位置调用它到它所在的目录,上述所有都是合法调用。 %~0 去掉了最后一个例子中的引号,而 %0 没有。

    因为这些都给出不同的结果,%0%~0 不太可能是您真正想要使用的。

    这里有一个批处理文件来说明:

    @echo Full path and filename: %~f0
    @echo Drive: %~d0
    @echo Path: %~p0
    @echo Drive and path: %~dp0
    @echo Filename without extension: %~n0
    @echo Filename with    extension: %~nx0
    @echo Extension: %~x0
    @echo Filename as given on command line: %0
    @echo Filename as given on command line minus quotes: %~0
    @REM Build from parts
    @SETLOCAL
    @SET drv=%~d0
    @SET pth=%~p0
    @SET fpath=%~dp0
    @SET fname=%~n0
    @SET ext=%~x0
    @echo Simply Constructed name: %fpath%%fname%%ext%
    @echo Fully  Constructed name: %drv%%pth%%fname%%ext%
    @ENDLOCAL
    pause
    

    【讨论】:

      【解决方案5】:

      尝试运行下面的示例,以感受神奇变量的工作原理。

      @echo off
      
      SETLOCAL EnableDelayedExpansion
      
      echo Full path and filename: %~f0
      echo Drive: %~d0
      echo Path: %~p0
      echo Drive and path: %~dp0
      echo Filename without extension: %~n0
      echo Filename with    extension: %~nx0
      echo Extension: %~x0
      
      echo date time : %~t0
      echo file size: %~z0
      
      ENDLOCAL
      

      相关规则如下。

      %~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
      %~$PATH:I   - searches the directories listed in the PATH
                     environment variable and expands %I to the
                     fully qualified name of the first one found.
                     If the environment variable name is not
                     defined or the file is not found by the
                     search, then this modifier expands to the
                     empty string
      

      【讨论】:

        【解决方案6】:

        下面是我的初始代码:

        @echo off
        Set z=%%
        echo.
        echo %z%0.......%0
        echo %z%~0......%~0
        echo %z%n0......%n0
        echo %z%x0......%x0
        echo %z%~n0.....%~n0
        echo %z%dp0.....%dp0
        echo %z%~dp0....%~dp0
        echo.
        

        我注意到 %~0 和 %0 给出的文件名是它在命令 shell 中输入的方式,而不是该文件的实际命名方式。因此,如果您希望文件名使用文字大小写,则应使用 %~n0。但是,这将省略文件扩展名。但是,如果您知道文件名,则可以添加 以下代码。

        set b=%~0
        echo %~n0%b:~8,4%
        

        我了解到 ":~8,4%" 表示从变量的第 9 个字符开始,然后显示接下来的 4 个字符。范围是 0 到变量字符串的末尾。所以 %Path% 会很长!

        fIlEnAmE.bat
        012345678901
        

        但是,这不如上面Jool 的解决方案(%~x0) 好。

        我的证据:

        C:\bin>filename.bat
        
        %0.......filename.bat
        %~0......filename.bat
        . . .
        
        C:\bin>fIlEnAmE.bat
        
        %0.......fIlEnAmE.bat
        %~0......fIlEnAmE.bat
        %n0......n0
        %x0......x0
        %~n0.....FileName
        %dp0.....dp0
        %~dp0....C:\bin\
        
        %~n0%b:~8,4%...FileName.bat
        
        Press any key to continue . . .
        
        C:\bin>dir
         Volume in drive C has no label.
         Volume Serial Number is CE18-5BD0
        
         Directory of C:\bin
        . . .
        05/02/2018  11:22 PM               208 FileName.bat
        

        这是最终代码

        @echo off
        Set z=%%
        set b=%~0
        echo.
        echo %z%0.......%0
        echo %z%~0......%~0
        echo %z%n0......%n0
        echo %z%x0......%x0
        echo %z%~n0.....%~n0
        echo %z%dp0.....%dp0
        echo %z%~dp0....%~dp0
        echo.
        echo A complex solution:
        echo ===================================
        echo %z%~n0%z%b:~8,4%z%...%~n0%b:~8,4%
        echo ===================================
        echo.
        echo The preferred solution:
        echo ===================================
        echo %z%~n0%z%~x0.......%~n0%~x0
        echo ===================================
        pause
        

        【讨论】:

        • 我可能遗漏了一些东西,但对我来说,你的最终脚本示例的复杂解决方案对我不起作用。至少如果脚本名为“ScriptPathTest.cmd”则不会。如果您执行“set b=%~snx0”,它会起作用,以便将其设置为“SCRIPT~1.cmd”,然后您将最后四个照常使用,但此时您不妨只执行 set b=% ~x0 并使用 %b% OR ... 就像你在首选的一样使用 %~x0 。 =P
        • 还应该注意 %0 在被调用函数中不起作用,所以我喜欢将脚本启动为:@( echo off & setlocal EnableDelayedExpansion & set _previous_errorlevel_=%ERRORLEVEL% & set _script_name_ =%~0 & ( call :run %* || goto :exit_failure ) & goto :exit_success ) .. 在实践中 &s 是换行符。对于那些想知道的人,我存储了以前的错误级别,以防用户使用 /?、-h、--h 调用脚本。 -help 或 --help 所以我不会为他们不必要地覆盖它。
        • 嗯...似乎 %0 或 %~0 WITH NO LETTERS 为您提供了一个被调用的子例程名称,但如果您使用 %~n0, %~x0, %~nx0, %~f0等,您将获得脚本名称的等价物。所以要么预先存储它,要么确保你总是使用字母。
        猜你喜欢
        • 2021-03-20
        • 1970-01-01
        • 2010-09-05
        • 2012-06-15
        • 1970-01-01
        • 2010-12-24
        • 2014-09-05
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多