【问题标题】:Batch: Remove file extension批处理:删除文件扩展名
【发布时间】:2011-03-14 00:44:23
【问题描述】:

我有以下来自维基百科的批处理脚本:

@echo off
    for /R "C:\Users\Admin\Ordner" %%f in (*.flv) do (
    echo %%f
)
pause

在 for 循环中,所有扩展名为 flv 的文件都会得到回显, 但我想对文件进行一些操作 我需要一次不带扩展名的文件和一次带扩展名的文件。 我怎么能得到这两个?

我搜索了解决方案,但没有找到。 我是一个真正的批处理新手...

【问题讨论】:

    标签: file batch-file


    【解决方案1】:

    如果您的变量是一个参数,您可以简单地使用%~dpn(用于路径)或%~n(仅用于名称)后跟参数编号,因此您不必担心扩展长度的变化。

    例如%~dpn0 将返回批处理文件的路径,不带扩展名,%~dpn1 将是%1,不带扩展名,等等。

    %~n0 将返回批处理文件的名称,不带扩展名,%~n1 将是%1,不带路径和扩展名等。

    完整的内容是%~dpnf0,当您仔细查看时,它开始变得有意义:

    • ddrive
    • ppath
    • nname,并且
    • ff文件扩展

    【讨论】:

    • 谢谢! %~dpn 保留了除扩展名之外的整个文件路径,而 %~nf 以某种方式保留了扩展名。
    • @GuillaumeF。是的,感谢您指出这一点。我更新了我的答案,以便更深入地了解这些字母。
    • ffilename,x 是 ex张力
    【解决方案2】:

    不循环

    如果我只是想从文件名或变量中删除扩展名(不列出任何目录或现有文件),我正在使用它:

    for %%f in ("%filename%") do set filename=%%~nf
    

    如果您想从完整路径中删除扩展名,请改用%%dpnf

    for %%f in ("%path%") do set path=%%~dpnf
    

    示例:

    (直接在控制台中使用)

    @for %f in ("file name.dat") do @echo %~nf
    @for %f in ("C:\Dir\file.dat") do @echo %~dpnf
    
    OUTPUT:
    
    file name
    C:\Dir\file
    

    【讨论】:

      【解决方案3】:

      您可以使用%%~nf 仅按照for 的参考中所述获取文件名:

      @echo off
          for /R "C:\Users\Admin\Ordner" %%f in (*.flv) do (
          echo %%~nf
      )
      pause
      

      以下选项可用:

      带修饰符的变量 描述 %~I 扩展 %I 删除任何周围的 引号 ("")。 %~fI 将 %I 扩展为完全限定的路径名​​。 %~dI 仅将 %I 扩展为驱动器号。 %~pI 仅将 %I 扩展为路径。 %~nI 仅将 %I 扩展为文件名。 %~xI 仅将 %I 扩展为文件扩展名。 %~sI 扩展路径以仅包含短名称。 %~aI 将 %I 扩展为 file 的文件属性。 %~tI 将 %I 扩展为文件的日期和时间。 %~zI 将 %I 扩展为文件大小。 %~$PATH:I 搜索PATH环境中列出的目录 变量并将 %I 扩展为 找到的第一个。如果环境变量名是 未定义或搜索未找到该文件, 此修饰符扩展为空字符串。

      【讨论】:

      • 请注意:在上面的示例中,%%f 类似于 C:\Users\Admin\Ordner\foo.flv,而 %%~nf 会为您提供 @ 987654326@。如果你想要所有 除了 扩展使用 %%~df%%~pf%%~nf 这会给你C:\Users\Admin\Ordner\foo
      • @ehambright 迟到的评论,但我想使用 %%~dpnf 会更短。
      • 感谢 Dirk 的修饰符/描述表。我的案例是在批处理脚本中从参数%1 获取不带扩展名的文件名。 echo %~n1 是我所追求的。
      【解决方案4】:

      使用 cygwin bash 进行切割

        :: e.g. FILE=basename.mp4 => FILE_NO_EXT=basename
        set FILE=%1
        for /f "delims=" %%a in ('bash -c "FILE=%FILE%; echo ${FILE/.*/}" ') do set FILE_NO_EXT=%%a
      

      【讨论】:

        【解决方案5】:

        这是一个非常晚的响应,但我想出了这个来解决我在使用 DiskInternals LinuxReader 将“.efs_ntfs”附加到它保存到非 NTFS (FAT32) 目录的文件时遇到的一个特殊问题:

        @echo off
        REM %1 is the directory to recurse through and %2 is the file extension to remove
        for /R "%1" %%f in (*.%2) do (
            REM Path (sans drive) is given by %%~pf ; drive is given by %%~df
            REM file name (sans ext) is given by %%~nf ; to 'rename' files, move them
            copy "%%~df%%~pf%%~nf.%2" "%%~df%%~pf%%~nf"
            echo "%%~df%%~pf%%~nf.%2" copied to "%%~df%%~pf%%~nf"
        echo.
        )
        pause
        

        【讨论】:

        • 我不确定它是否回答了所提出的问题,但它确实帮助了我,谢谢!
        • @matan7890 是的;该操作没有指定“我希望对文件进行一些操作”[原文如此]需要什么,但其中一项操作可能是重命名它们,在这种情况下,我的答案是对已接受答案的扩展。
        • 这帮助了我的一个朋友,他打开了一个附件并将.encrypted 添加到他的所有文件中,并要求赎金。显然,攻击脚本必须是一个与此相反的批处理文件,并将.encrypted添加到所有文件中。
        • 赞成,因为您提到了与 的输出最相似的驱动器、路径和扩展名 (%%~df%%~pf%%~nf) %%f 来自原始问题,而不是 just 没有扩展名的文件名 (%%~nf)
        【解决方案6】:

        如果您的变量保存的文件实际上不存在,FOR 方法将不起作用。如果您知道扩展的长度,您可以使用的一个技巧是采用子字符串:

        %var:~0,-4%
        

        -4 表示最后 4 位数字(大概是 .ext)将被截断。

        【讨论】:

        • 这对我不起作用(在 Win8.1 上)——也许我在问题中使用的示例上下文中尝试 echo %f:~0,-4% 时误解了它。我做错了什么?
        • 显然这适用于“正常”变量,而不是 FOR 变量(或者我可能只是不知道正确的语法)。无论如何,这将在 OP 示例的上下文中起作用:SET fl=%%f 然后echo %fl:~0,-4%
        • @Wolf 您需要将循环变量的值设置为普通变量,然后在普通变量中进行字符串替换/截断
        • 在足够多的情况下,扩展长度不等于 3 或未知。即使文件不存在,您仍然可以使用 for,请参阅我的回答。
        【解决方案7】:

        我对 windows cmd 也很陌生,但是试试这个:

        echo %%~nf
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2011-09-18
          • 1970-01-01
          • 1970-01-01
          • 2019-10-18
          • 2018-09-05
          • 2013-01-04
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多