AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / ubuntu / 问题 / 35922
In Process
tommyk
tommyk
Asked: 2011-04-20 04:02:25 +0800 CST2011-04-20 04:02:25 +0800 CST 2011-04-20 04:02:25 +0800 CST

如何从命令行递归更改多个文件的扩展名?

  • 772

我有许多带有.abc扩展名的文件,并想将它们更改为.edefg
如何从命令行执行此操作?

我有一个包含许多子文件夹的根文件夹,因此该解决方案应该递归工作。

command-line
  • 9 9 个回答
  • 149231 Views

9 个回答

  • Voted
  1. geirha
    2011-04-20T10:51:57+08:002011-04-20T10:51:57+08:00

    一种可移植的方式(适用于任何符合 POSIX 的系统):

    find /the/path -depth -name "*.abc" -exec sh -c 'mv "$1" "${1%.abc}.edefg"' _ {} \;
    

    在 bash4 中,您可以使用 globstar 来获取递归 glob (**):

    shopt -s globstar
    for file in /the/path/**/*.abc; do
      mv "$file" "${file%.abc}.edefg"
    done
    

    Ubuntu 中的 (perl)rename命令可以使用 perl 正则表达式语法重命名文件,您可以将其与 globstar 或find:

    # Using globstar
    shopt -s globstar
    files=(/the/path/**/*.abc)  
    
    # Best to process the files in chunks to avoid exceeding the maximum argument 
    # length. 100 at a time is probably good enough. 
    # See http://mywiki.wooledge.org/BashFAQ/095
    for ((i = 0; i < ${#files[@]}; i += 100)); do
      rename 's/\.abc$/.edefg/' "${files[@]:i:100}"
    done
    
    # Using find:
    find /the/path -depth -name "*.abc" -exec rename 's/\.abc$/.edefg/' {} +
    

    另请参阅http://mywiki.wooledge.org/BashFAQ/030

    • 112
  2. Chakra
    2011-04-20T04:23:09+08:002011-04-20T04:23:09+08:00

    如果所有文件都在同一个文件夹中,这将完成所需的任务

    rename 's/.abc$/.edefg/' *.abc
    

    要递归地重命名文件,请使用以下命令:

    find /path/to/root/folder -type f -name '*.abc' -print0 | xargs -0 rename 's/.abc$/.edefg/'
    
    • 55
  3. Christian Long
    2012-10-06T14:48:20+08:002012-10-06T14:48:20+08:00

    递归重命名的一个问题是,无论您使用哪种方法来定位文件,它都会将整个路径传递给rename,而不仅仅是文件名。这使得在嵌套文件夹中进行复杂的重命名变得困难。

    我用find's -execdiraction来解决这个问题。如果您使用-execdir而不是-exec,则从包含匹配文件的子目录运行指定的命令。因此,它不会将整个路径传递给rename,而是仅传递./filename。这使得编写正则表达式变得更加容易。

    find /the/path -type f \
                   -name '*.abc' \
                   -execdir rename 's/\.\/(.+)\.abc$/version1_$1.abc/' '{}' \;
    

    详细地:

    • -type f意味着只查找文件,而不是目录
    • -name '*.abc'表示仅匹配以 .abc 结尾的文件名
    • '{}'是标记-execdir将插入找到的路径的位置的占位符。需要单引号,以允许它处理带有空格和 shell 字符的文件名。
    • -type和之后的反斜杠-name是 bash 行继续字符。我使用它们来使这个示例更具可读性,但是如果您将命令全部放在一行上,则不需要它们。
    • 但是,-execdir行尾的反斜杠是必需的。它用于转义分号,该分号终止由-execdir. 乐趣!

    正则表达式的解释:

    • s/正则表达式的开始
    • \.\/匹配 -execdir 传入的前导 ./ 。使用 \ 转义 . 和 / 元字符(注意:这部分因您的 . 版本而异find。请参阅用户 @apollo 的评论)
    • (.+)匹配文件名。括号捕获匹配以供以后使用
    • \.abc转义点,匹配 abc
    • $将匹配锚定在字符串的末尾

    • /标记正则表达式“匹配”部分的结束,以及“替换”部分的开始

    • version1_将此文本添加到每个文件名

    • $1引用现有文件名,因为我们用括号捕获它。如果您在“匹配”部分使用多组括号,您可以在此处使用 $2、$3 等来引用它们。
    • .abc新文件名将以 .abc 结尾。无需在“替换”部分中转义点元字符
    • /正则表达式的结尾

    前

    tree --charset=ascii
    
    |-- a_file.abc
    |-- Another.abc
    |-- Not_this.def
    `-- dir1
        `-- nested_file.abc
    

    后

    tree --charset=ascii
    
    |-- version1_a_file.abc
    |-- version1_Another.abc
    |-- Not_this.def
    `-- dir1
        `-- version1_nested_file.abc
    

    提示:rename's -n 选项很有用。它会进行试运行并向您显示它将更改的名称,但不会进行任何更改。

    • 15
  4. aNeutrino
    2013-02-04T08:36:59+08:002013-02-04T08:36:59+08:00

    另一种便携方式:

    find /the/path -depth -type f -name "*.abc" -exec sh -c 'mv -- "$1" "$(dirname "$1")/$(basename "$1" .abc).edefg"' _ '{}' \;
    
    • 5
  5. ashanrupasinghe
    2016-08-23T04:12:53+08:002016-08-23T04:12:53+08:00
    # Rename all *.txt to *.text
    for f in *.txt; do 
    mv -- "$f" "${f%.txt}.text"
    done
    

    另请参阅有关为什么不应该解析的条目ls。

    编辑:如果你必须使用 basename 你的语法是:

    for f in *.txt; do
    mv -- "$f" "$(basename "$f" .txt).text"
    done
    

    https://unix.stackexchange.com/questions/19654/changeing-extension-to-multiple-files

    • 4
  6. MvG
    2018-05-21T13:13:45+08:002018-05-21T13:13:45+08:00

    我会使用同名包中的 mmv命令:

    mmv ';*.abc' '#1#2.edefg'
    

    ;匹配零个或多个并且*/对应#1于替换。*对应#2于。非递归版本将是

    mmv '*.abc' '#1.edefg'
    
    • 2
  7. KhoPhi
    2016-03-14T13:58:52+08:002016-03-14T13:58:52+08:00

    这就是我所做的,并且按照我想要的方式工作。我使用了mv命令。我有多个.3gp文件,我想将它们全部重命名为.mp4

    这是一个简短的oneliner:

    for i in *.3gp; do mv -- "$i" "ren-$i.mp4"; done
    

    它只是扫描当前目录,选择所有 .3gp 文件,然后重命名(使用 mv)为ren-name_of_file.mp4

    • 0
  8. Peaceful
    2017-09-27T19:39:16+08:002017-09-27T19:39:16+08:00

    我找到了一种简单的方法来实现这一点。要将许多文件的扩展名从 jpg 更改为 pdf,请使用:

    for file in /path/to; do mv $file $(basename -s jpg $file)pdf ; done
    
    • 0
  9. Ciro Santilli OurBigBook.com
    2019-01-13T13:23:53+08:002019-01-13T13:23:53+08:00

    重命名文件和目录find -execdir | rename

    如果您要重命名文件和目录而不是简单地使用后缀,那么这是一个很好的模式:

    PATH="$(echo "$PATH" | sed -E 's/(^|:)[^\/][^:]*//g')" \
      find . -depth -execdir rename 's/findme/replaceme/' '{}' \;
    

    awesome-execdir选项cd在执行命令之前进入目录rename,不像-exec.

    -depth确保重命名首先发生在孩子身上,然后是父母身上,以防止缺少父目录的潜在问题。

    -execdir是必需的,因为 rename 不能很好地与非基本名称输入路径一起使用,例如以下失败:

    rename 's/findme/replaceme/g' acc/acc
    

    之所以PATH需要进行黑客攻击,是因为-execdir有一个非常烦人的缺点:如果您的环境变量中有任何相对路径,find则非常固执己见并且拒绝做任何事情,例如,失败:-execdirPATH./node_modules/.bin

    find:相对路径 './node_modules/.bin' 包含在 PATH 环境变量中,与 find 的 -execdir 操作结合使用是不安全的。请从 $PATH 中删除该条目

    另请参阅:为什么使用 '-execdir' 操作对于 PATH 中的目录不安全?

    -execdir是 POSIX 的 GNU find扩展。rename是基于 Perl 的,来自rename包。在 Ubuntu 18.10 中测试。

    重命名前瞻解决方法

    如果您的输入路径不是来自find,或者如果您已经受够了相对路径的烦恼,我们可以使用一些 Perl 前瞻来安全地重命名目录,如下所示:

    git ls-files | sort -r | xargs rename 's/findme(?!.*\/)\/?$/replaceme/g' '{}'
    

    我还没有找到一个方便的类比-execdir:xargshttps: //superuser.com/questions/893890/xargs-change-working-directory-to-file-path-before-executing/915686

    sort -r需要确保文件位于其各自目录之后,因为较长的路径位于具有相同前缀的较短路径之后。

    • 0

相关问题

  • 如何从命令行仅安装安全更新?关于如何管理更新的一些提示

  • 如何从命令行刻录双层 dvd iso

  • 如何从命令行判断机器是否需要重新启动?

  • 文件权限如何工作?文件权限用户和组

  • 如何在 Vim 中启用全彩支持?

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    如何运行 .sh 脚本?

    • 16 个回答
  • Marko Smith

    如何安装 .tar.gz(或 .tar.bz2)文件?

    • 14 个回答
  • Marko Smith

    我需要什么命令来解压缩/提取 .tar.gz 文件?

    • 8 个回答
  • Marko Smith

    如何列出所有已安装的软件包

    • 24 个回答
  • Marko Smith

    无法锁定管理目录 (/var/lib/dpkg/) 是另一个进程在使用它吗?

    • 25 个回答
  • Marko Smith

    如何使用命令行将用户添加为新的 sudoer?

    • 7 个回答
  • Marko Smith

    更改文件夹权限和所有权

    • 9 个回答
  • Martin Hope
    EmmyS 我需要什么命令来解压缩/提取 .tar.gz 文件? 2011-02-09 14:50:41 +0800 CST
  • Martin Hope
    Ivan 如何列出所有已安装的软件包 2010-12-17 18:08:49 +0800 CST
  • Martin Hope
    La Ode Adam Saputra 无法锁定管理目录 (/var/lib/dpkg/) 是另一个进程在使用它吗? 2010-11-30 18:12:48 +0800 CST
  • Martin Hope
    David Barry 如何从命令行确定目录(文件夹)的总大小? 2010-08-06 10:20:23 +0800 CST
  • Martin Hope
    jfoucher “以下软件包已被保留:”为什么以及如何解决? 2010-08-01 13:59:22 +0800 CST
  • Martin Hope
    David Ashford 如何删除 PPA? 2010-07-30 01:09:42 +0800 CST

热门标签

10.10 10.04 gnome networking server command-line package-management software-recommendation sound xorg

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve