在目录中递归查找和替换文件名

时间:2012-02-22 11:07:55

标签: bash

我想将以123_xxx.txt开头的文件夹中的所有文件重命名为xxx.txt

例如,我的目录有:

123_xxx.txt
123_yyy.txt
123_zzz.txt

I want to rename all files as:

xxx.txt
yyy.txt
zzz.txt

我在这个论坛上看到了一些有用的bash脚本,但我仍然对如何将它用于我的要求感到困惑。

让我们假设我使用:

for file in `find -name '123_*.txt'` ; do mv $file {?.txt} ; done

这是正确的方法吗?

14 个答案:

答案 0 :(得分:65)

这样做:

find . -name '123*.txt' -type f -exec bash -c 'mv "$1" "${1/\/123_//}"' -- {} \;

优点:

  • 没有管道,没有读取,没有机会破坏格式错误的文件名。
  • 只有一个非标准工具或功能:bash。

答案 1 :(得分:20)

find -name "123*.txt" -exec rename 's/^123_//' {} ";" 

会做到的。没有AWK,没有,没有需要xargs,但是重命名,这是Perl lib中非常有用的命令。它并不总是包含在Linux中,但很容易从repos安装。

答案 2 :(得分:7)

你可以检查'重命名'工具

例如

rename 's/^123_//' *.txt

或(需要gawk)

find . -name '123_*.txt'|awk '{print "mv "$0" "gensub(/\/123_(.*\.txt)$/,"/\\1","g");}'|sh

<强>测试

kent$  tree
.
|-- 123_a.txt
|-- 123_b.txt
|-- 123_c.txt
|-- 123_d.txt
|-- 123_e.txt
`-- u
    |-- 123_a.txt
    |-- 123_b.txt
    |-- 123_c.txt
    |-- 123_d.txt
    `-- 123_e.txt

1 directory, 10 files

kent$  find . -name '123_*.txt'|awk '{print "mv "$0" "gensub(/\/123_(.*\.txt)$/,"/\\1","g");}'|sh

kent$  tree
.
|-- a.txt
|-- b.txt
|-- c.txt
|-- d.txt
|-- e.txt
`-- u
    |-- a.txt
    |-- b.txt
    |-- c.txt
    |-- d.txt
    `-- e.txt

1 directory, 10 files

答案 3 :(得分:7)

如果你想将名为foo的文件名中的字符串替换为bar,你可以在linux ubuntu中使用它,根据需要更改文件类型

find -name "*foo*.filetype" -exec rename 's/foo/bar/' {} ";"

答案 4 :(得分:3)

肯特的一个微小的变化,不需要gawk,而且更具可读性(虽然,这有点值得商榷......)

find . -name "123*" | awk '{a=$1; gsub(/123_/,""); printf "mv \"%s\" \"%s\"\n", a, $1}' | sh

答案 5 :(得分:2)

如果您的文件名中没有换行符:

find -name '123_*.txt' | while IFS= read -r file; do mv "$file" "${file#123_}"; done

如果您的find支持-print0标记(GNU find确实存在),那么以非常安全的方式:

find -name '123_*.txt' -print0 | while IFS= read -r -d '' file; do mv "$file" "${file#123_}"; done

答案 6 :(得分:1)

要展开Sorpigal's answer,如果您想将123_替换为hello_,可以使用

    find . -name '123*.txt' -type f -exec bash -c 'mv "$1" "${1/\/123_/\/hello_}"' -- {} \;

答案 7 :(得分:1)

你可以为它做一个小的bash脚本。 使用以下内容创建名为recursive_replace_filename的文件:

#!/bin/bash

if test $# -lt 2; then
  echo "usage: `basename $0` <to_replace> <replace_value>"
fi

for file in `find . -name "*$1*" -type f`; do
  mv "'$file'" "${file/'$1'/'$2'}"
done

使可执行文件运行:

$ chmod +x recursive_replace_filename
$ ./recursive_replace_filename 123_ ""

请注意,此脚本可能很危险,请确保您知道它正在执行的操作以及您正在执行它的文件夹以及使用哪些参数。在这种情况下,将重命名当前文件夹中包含123_的所有文件。

答案 8 :(得分:0)

使用util-linux重命名2.28.2我必须使用不同的语法:

find -name "*.txt" -exec rename -v "123_" ""  {} ";" 

答案 9 :(得分:0)

尝试了上面的答案,但是它对我不起作用,因为我同时在文件夹和文件名中包含了字符串,所以这是我执行以下bash脚本的目的:

  for fileType in d f
  do
    find  -type $fileType -iname "stringToSearch*" |while read file
    do
      mv $file $( sed -r "s/stringToSearch/stringToReplaceWith/" <<< $file )
    done
  done

首先,我先替换内部文件夹名称,然后替换内部文件名称。

答案 10 :(得分:0)

如果名称是固定的,则可以相当简单地访问每个目录并在子外壳中执行重命名(以避免更改当前目录)。这就是我将一堆new_paths.json文件重命名为paths.json的方式:

for file in $(find root_directory -name new_paths.json)
  do
     (cd $(dirname $file) ; mv new_paths.json paths.json)
  done

答案 11 :(得分:0)

在上面的示例中,我使用它替换了文件名的一部分...由于供应商更改了名称,因此用于重命名目录中的各种数据文件。

find . -name 'o3_cloudmed_*.*' -type f -exec bash -c 'mv "$1" "${1/cloudmed/revint}"' -- {} \;

答案 12 :(得分:0)

这是迄今为止唯一可行的解​​决方案:

find-rename-recursive --pattern '123_' --string '' -- . -type f -name "123_*"

所有其他解决方案都不适合我-甚至删除了一些文件!

有关详细信息,请参见https://github.com/l3x/helpers#find-rename-recursive

答案 13 :(得分:-2)

prename s/^123_// 123_*

prename in the official Perl5 wiki。复制为方便起见:

prename - 根据正则表达式重命名文件的脚本。 (原始发布的位置是什么?)最初命名为rename,它主要是作为prename发现的,因为原来的一个与util-linux包中的rename命令冲突。无数的叉子和重新实现: