DOS BAT文件中与Unix的basename命令等效的是什么?

50

有没有一种简单的方法,可以使用DOS BAT命令语言轻松获取DOS文件名的基本名称(不带扩展名)?

我同意:format c:\ 可能是一个很好的开始,然后是可启动的Linux CD(假设这些古董机器有CD读取器-不是必须的)。但让我们假装我们只有DOS......(也就是说:不是Windows-甚至不是Windows 3.1,更不用说Windows 95、98、NT、ME、XP、Vista、7等)


2
“basename” 保留文件扩展名。例如“/home/user/Desktop/test.txt” 变成 “test.txt”。这是您想要的功能吗?或者您只想要“test”这个文件名? - eldarerathis
1
@eldarerathis: Unix中的basename命令可以去除扩展名:basename /some/where/file.txt .txt会返回file,这是期望得到的结果。所需要去除的扩展名是已知的。 - Jonathan Leffler
啊,好的。那就清楚了。 - eldarerathis
2
哎呀,抱歉,我看错了 :-( 我道歉。可能是因为我对整个DOS问题有点过于热衷了。不过我想知道为什么你当时接受了那个答案,因为它显然在DOS中行不通。 - Joey
@JonathanLeffler,晚些感谢你替我提出这个问题。然而,我最终放弃了实模式DOS,转向使用Windows,使用PowerShell和vb.net进行脚本编写。Windows的cmd.exe CLI确实支持传统的DOS批处理脚本,但是你可以通过DotNet和PS做更多的事情。 - FrankRuperto
显示剩余3条评论
8个回答

56

对于命令行

for /F %i in ("c:\foo\bar.txt") do @echo %~ni

针对 .bat 文件

for /F %%i in ("c:\foo\bar.txt") do @echo %%~ni

输出: bar

如果路径中包含空格,需要像这样添加"delims=":

for /F "delims=" %i in ("c:\foo\bar baz.txt") do @echo %~ni

输出: bar baz

(进一步阅读:http://www.computerhope.com/forhlp.htm)


1
for /F %i in ("c:\foo\bar space.txt") do @echo %~ni 输出 "bar",如何获取 "bar space.txt"? - Ciantic
@Ciantic:通过阅读我的回答中的链接。或者以适当的方式提出问题。 - hobodave
8
我的回答是:for /F "delims=" %i in ("c:\foo\bar space.txt") do @echo %~ni 的结果是 "bar space"。 - Ciantic
如何将其设置为变量? - T.Todua
1
@T.Todua 不要使用 @echo %%~ni,请改为写入 set MY_VAR=%%~ni - Itay
显示剩余2条评论

45

为了进一步解释hobodavears的答案,这里是for命令的相关帮助片段:

In addition, substitution of FOR variable references has been enhanced.
You can now use the following optional syntax:

    %~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

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
    %~dp$PATH:I - searches the directories listed in the PATH
                   environment variable for %I and expands to the
                   drive letter and path of the first one found.
    %~ftzaI     - expands %I to a DIR like output line

In the above examples %I and PATH can be replaced by other valid
values.  The %~ syntax is terminated by a valid FOR variable name.
Picking upper case variable names like %I makes it more readable and
avoids confusion with the modifiers, which are not case sensitive.

4

我知道“你不能”这个答案不够好。所以,如果真的必须在实模式DOS下完成,那么获取4DOS命令壳和相关程序并使用它,而不是COMMAND.COM。

http://www.4dos.info/v4dos.htm

我已经多年没有使用它了,但它总是比COMMAND.COM好得多。如果您在此页面上搜索“basename”: http://www.4dos.info/4batfaq.htm 您将看到,在使用4DOS而不是COMMAND.COM时,有一个实模式DOS答案来解决您的问题。
我能想到的唯一其他解决方案路径是查找或编写执行basename的实模式.exe。
即使在带有所有支持外部命令的DOS 6.22中,COMMAND.COM始终是脚本/批处理文件的极其受限系统。请注意,MinGW32命令行程序将没有任何帮助。所有这些都是针对保护模式(32位Windows)的。如果您在DOS中尝试它,您将只会得到晦涩的“此程序无法在DOS模式下运行”或类似的消息。

4

完整的解决方案(即使路径包含空格)

.bat文件中

for /F "delims=" %%i in (%FILE_path%) do @echo "%%~ni"

在命令提示符中使用%代替%%(感谢 @Ciantic)

3

基于hobodave的接受答案,以下是如何在批处理文件中使用命令来设置变量:

for /F %%i in ("%1") do @set FN=%%~nxi

它使用第一个命令行参数 %1,并将变量 FN 设置为基本名称(例如 file.txt)。

3

DOS 6.22不支持在for批处理语句中使用%~nI。以下是解决我原始问题的方法,即isql的4.10 bcheck实用程序仅需要基本名称,而isql 2.10 bcheck实用程序可以使用star.star作为参数。我创建了以下QBASIC程序来解决bcheck 4.10现在需要仅使用基本名称才能工作的问题:

BatFile$ = "CHKFILE.BAT"
        IF INSTR(COMMAND$, "?") > 0 THEN
          PRINT
          PRINT "This program generates a batch file to check Informix files"
          PRINT "  -b  BBBB.BAT    this option is used to change the batch file name"
          PRINT "                  by default the batch file name is CHKFILE.BAT"
          PRINT
          SYSTEM
        END IF
        IF INSTR(COMMAND$, "-B") > 0 THEN
          BatFile$ = LTRIM$(MID$(COMMAND$, INSTR(COMMAND$, "-B") + 2)) + "  "
          BatFile$ = LEFT$(BatFile$, INSTR(BatFile$, " ") - 1)
        END IF

        OPEN BatFile$ FOR OUTPUT AS #2


        filename$ = DIR$("*.dat")
        IF LEN(filename$) = 0 THEN SYSTEM
        DO WHILE LEN(filename$) > 0
          PRINT #2, "bcheck -y", filename$
          filename$ = DIR$
        LOOP
        CLOSE
        SYSTEM

或者,可以编写一个ACE程序从systables.dirpath中提取文件名,并打印出"BCHECK -y "和systables.dirpath。


3

1
这个问题已经讨论过了...可以想象,那些仍然坚持使用DOS的人也坚持不使用MKS。 - Jonathan Leffler

2
FOR 循环命令中,你可以使用 %%~n

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