【问题标题】:How do I rename lots of files changing the same filename element for each in Linux?如何重命名大量文件,在 Linux 中为每个文件更改相同的文件名元素?
【发布时间】:2012-06-30 21:43:51
【问题描述】:

我正在尝试重命名在文件名或文本内容中包含公司名称的大量文件(我数超过 200 个)。我基本上需要将对“公司”的任何引用更改为“新公司”,在适用的情况下保持大写(即“公司变为新公司”,“公司”变为“新公司”)。我需要递归地执行此操作。

因为该名称几乎可以出现在我无法在任何满足我要求的任何地方找到示例代码的任何地方。它可以是这些示例中的任何一个,或者更多:

company.jpg
company.php
company.Class.php
company.Company.php
companysomething.jpg

希望你能理解。我不仅需要处理文件名,还需要处理文本文件的内容,例如 HTML 和 PHP 脚本。我假设这将是第二个命令,但我不完全确定是什么。

我搜索了代码库,发现在近 300 个文件中提到了近 2000 次公司名称,所以我不喜欢手动进行。

请帮忙! :)

【问题讨论】:

  • 重命名并删除了递归。这实际上与递归无关(所有多个操作都不是递归!),而是关于 - 见新标题。
  • 抱歉,似乎很多人在谷歌搜索问题时都在问同样的问题。它以与 chmod -R 或 chown -R 相同的方式递归地遍历所有目录,因此它似乎是显而易见的标题。文件不是都在同一个目录下,而是都在这个目录下或者子目录下

标签: linux shell rename file-rename


【解决方案1】:

bash 具有强大的循环和替换能力:

for filename in `find /root/of/where/files/are -name *company*`; do
    mv $filename ${filename/company/newcompany}
done
for filename in `find /root/of/where/files/are -name *Company*`; do
    mv $filename ${filename/Company/Newcompany}
done

【讨论】:

  • 我可能以某种方式对其进行了哈希处理,不确定。我明白了:意外标记 `mv' 附近的语法错误
  • 我丢失了一个;,现已修复
  • 魔术!这样可行。现在我只需要对引用公司和公司的文件的内容进行排序。简单有效的那个,谢谢
  • 我发现我认为也是编辑文件内容的解决方案:find ./ -type f -exec sed -i 's/company/newcompany/' {} \;我想我可能错过了一些东西,因为它似乎只是替换了文件中的第一个实例。否则,这将填补其余的空白,以及您出色而简单的脚本。谢谢
  • 尝试将s/company/newcompany/ 更改为s/company/newcompany/g - g 用于全局
【解决方案2】:

对于文件和目录名称,使用forfindmvsed

对于名称中包含 company 的每个路径 (f),将其 (mv) 从 f 重命名为新名称,其中 company 将替换为 newcompany

for f in `find -name '*company*'` ; do mv "$f" "`echo $f | sed s/company/nemcompany/`" ; done

对于文件内容,使用findxargssed

对于每个文件,将其内容中的company 更改为newcompany,保留带有扩展名.backup 的原始文件。

find -type f -print0 | xargs -0 sed -i .bakup 's/company/newcompany/g'

【讨论】:

    【解决方案3】:

    我建议你看看 man rename 一个非常强大的 perl 实用程序,用于重命名文件。

    标准语法是

    rename 's/\.htm$/\.html/' *.htm
    

    聪明的部分是该工具接受任何 perl-regexp 作为要更改的文件名的模式。

    您可能希望使用-n 开关运行它,这将使该工具仅报告它会更改的内容。

    目前无法找到保持大写的好方法,但由于您已经可以搜索文件结构,请发出多个不同大小写的rename,直到所有文件都被更改。

    要遍历当前文件夹下的所有文件并搜索特定字符串,您可以使用

    find . -type f -exec grep -n -i STRING_TO_SEARCH_FOR /dev/null {} \;
    

    该命令的输出可以定向到一个文件(经过一些过滤以提取需要更改的文件的文件名)。

    find . /type ... > files_to_operate_on
    

    然后将其包装在 while read 循环中并为 inplace-replacement 执行一些 perl-magic

    while read file
    do
        perl -pi -e 's/stringtoreplace/replacementstring/g' $file
    done < files_to_operate_on
    

    【讨论】:

      【解决方案4】:

      递归处理文件的正确方法很少。这是一个:

      while IFS= read -d $'\0' -r file ; do
          newfile="${file//Company/Newcompany}"
          newfile="${newfile//company/newcompany}"
          mv -f "$file" "$newfile"
      done < <(find /basedir/ -iname '*company*' -print0)
      

      这将适用于所有可能的文件名,而不仅仅是其中没有空格的文件名。

      假设是 bash。

      对于更改文件的内容,我建议谨慎,因为如果文件不是纯文本,文件中的盲目替换可能会破坏事情。也就是说,sed 就是为这种事情而生的。

      while IFS= read -d $'\0' -r file ; do
          sed -i '' -e 's/Company/Newcompany/g;s/company/newcompany/g'"$file"
      done < <(find /basedir/ -iname '*company*' -print0)
      

      对于这次运行,我建议向find 添加一些额外的开关,以限制它将处理的文件,也许

      find /basedir/ \( -iname '*company*' -and \( -iname '*.txt' -or -ianem '*.html' \) \) -print0
      

      【讨论】:

      • 谢谢。我最终使用了我在其他地方找到的 sed 解决方案,但它似乎只取代了第一次出现。不得不继续运行它或手动完成它。不过为我做了最多,这很好:) 这是命令:find ./ -type f -exec sed -i 's/company/newcompany/' {} \;
      • @AntTheKnee:sed s/// 表达式只会替换第一个实例。您需要添加 g ("global") 选项以使其每行替换多个实例,例如s///g,正如您在我的示例中看到的那样。
      • 很高兴知道。非常感谢:)
      猜你喜欢
      • 1970-01-01
      • 2016-07-22
      • 1970-01-01
      • 2011-01-04
      • 1970-01-01
      • 2021-08-20
      • 2023-02-13
      • 1970-01-01
      • 2013-12-13
      相关资源
      最近更新 更多