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

use*_*606 37 bash

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

例如,我的目录有:

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

I want to rename all files as:

xxx.txt
yyy.txt
zzz.txt
Run Code Online (Sandbox Code Playgroud)

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

让我们假设我使用:

for file in `find -name '123_*.txt'` ; do mv $file {?.txt} ; done
Run Code Online (Sandbox Code Playgroud)

这是正确的方法吗?

Sor*_*gal 69

这样做:

find . -name '123*.txt' -type f -exec bash -c 'mv "$1" "${1/\/123_//}"' -- {} \;
Run Code Online (Sandbox Code Playgroud)

好处:

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

  • @tronda是这样的:`找到.-name'123*.txt'-type f -exec bash -c'mv"$ 1""$ {1 /\/ 123_/hello /}"' - {} \;` (14认同)
  • 如果不是删除字符串,我想用其他字符串替换它,如"hello"? (9认同)
  • @Sorpigal我发现`\ /`和最后一个`/`是不必要的.所以``$ {1/companyA/companyB}"`运作良好. (8认同)
  • @AmagicalFishy:一个详尽的解释会溢出这个评论框.这里发生的事情是,引号内的`-c`之后的所有内容实际上都是一个bash脚本并被解释为这样.以下`--`是任意的,并且被bash用作oneliner脚本的"文件名".`{}`是语法`find`用作每个文件名的占位符,`\;`告诉`find`这结束了`-exec`选项.你应该真的"找到`并阅读`-exec`,然后查看shell脚本,从`man bash`开始并查看`-c`选项. (6认同)
  • 我知道这是一个旧线程,但有人可以解释所有符号的含义吗? (4认同)
  • 这是利用[参数扩展](https://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_0602)从路径末尾剥离基本名称,然后附加一个新名称删除了最多 123_ 的前缀。要阅读的两个运算符是“%”和“##”,其余的是简单的通配符。 (2认同)

use*_*own 22

find -name "123*.txt" -exec rename 's/^123_//' {} ";" 
Run Code Online (Sandbox Code Playgroud)

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

  • 首先在 Mac 上安装“brew install rename” (3认同)
  • @HodorTheCoder如果你在bash中设置了`globstar`(`shopt -s globstar`),你可以递归地执行:`rename 's/^123_//' **/*` (3认同)
  • 您在 -name 之前错过了一个点 (.),不能在 mac 上运行 (2认同)
  • 除此之外,如果您仅在谈论单个目录中的文件,则无需使用find。始终最好使它尽可能简单,因此您可以执行`rename's / ^ 123 _ //'*`并且它会做完全相同的事情。干杯。 (2认同)

Ken*_*ent 7

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

例如

rename 's/^123_//' *.txt
Run Code Online (Sandbox Code Playgroud)

或者(需要gawk)

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

测试:

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
Run Code Online (Sandbox Code Playgroud)

  • 你应该提到同音异义陷阱:你谈论了特殊的 rename 命令,它从 util-linux 中篡夺了 rename 的名称(它不处理正则表达式)。 (2认同)

tal*_*ony 7

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

find -name "*foo*.filetype" -exec rename 's/foo/bar/' {} ";"
Run Code Online (Sandbox Code Playgroud)

  • 这是最有用的概括答案 (2认同)

Pat*_*t O 6

为了扩展Sorpigal 的答案,如果你想用 替换123_hello_你可以使用

    find . -name '123*.txt' -type f -exec bash -c 'mv "$1" "${1/\/123_/\/hello_}"' -- {} \;
Run Code Online (Sandbox Code Playgroud)