我有一个文件夹,里面全是‘四位数字,空格,字母数字字符串.txt’格式的文本文件.例如:

$ touch '0001 jko0001.txt'  '0002 jko0002.txt'  '0003 jko0003.txt'

$ ls
'0001 jko0001.txt'  '0002 jko0002.txt'  '0003 jko0003.txt'

我想要重命名这些文件,以便删除前导数字和空格.因为我有很多文件,所以我使用find将文件名传递给rename.我try 使用以下命令执行此操作:

find . -type f -name '*.txt' -print0 | xargs -0 rename -n -- 's/^\d{4}\s+//' {} +

然而,这失败了.(是的,-n仅用于打印更改,而不重命名文件.即使我移除它,它也会失败).

有趣的是,如果我将命令分成几个部分,它确实可以工作:

$ find . -type f -name '*.txt'
./0003 jko0003.txt
./0002 jko0002.txt
./0001 jko0001.txt

$ rename -n -- 's/^[0-9]{4}\s+//' *.txt
0001 jko0001.txt -> jko0001.txt
0002 jko0002.txt -> jko0002.txt
0003 jko0003.txt -> jko0003.txt

$ bash --version
GNU bash, version 5.1.16(1)-release (x86_64-pc-linux-gnu)

但当与xargs结合在一起时,它就失败了.为什么?

此外,我甚至不能让它在find-execdir分下工作:

find . -type f -name '*.txt' -execdir rename -n -- 's/^\d{4} //' {} \;

这些都不管用.

find . -type f -name '*.txt' -print0 | xargs -0 rename -n -- 's/^\d{4}\s+//' "{}" +
find . -type f -name '*.txt' -print0 | xargs -0 rename -n -- 's/^[0-9]{4}\s+//' "{}" +
find . -type f -name '*.txt' -execdir rename -n -- 's/^\d{4} //' {} \;
find . -type f -name '*.txt' -execdir rename -n -- 's/^\d{4} //' '{}' \;

提前谢谢!

推荐答案

这里至少有两个问题.首先,find传递的是文件的路径,而不仅仅是文件名(是的,即使使用-execdir也是如此).因此,将-d选项添加到rename,以告诉它只对文件名执行操作,而不是对完整路径执行操作.

其次,您将find -exec语法和xargs语法混淆在一起.具体地说,命令末尾的{} +用于find -exec,not用于xargs(注意:在某些模式下,xargs使用{},但它从不使用+).要修复该问题,请移除{} +并使用标准xargs语法:

$ find . -type f -name '*.txt' -print0 | xargs -0 rename -n -d -- 's/^\d{4}\s+//'
rename(./0003 jko0003.txt, ./jko0003.txt)
rename(./0001 jko0001.txt, ./jko0001.txt)
rename(./0002 jko0002.txt, ./jko0002.txt)

或者跳过xargs,直接使用find -exec(这次是with{} +):

$ find . -type f -name '*.txt' -exec rename -n -d -- 's/^\d{4}\s+//' {} +
rename(./0003 jko0003.txt, ./jko0003.txt)
rename(./0001 jko0001.txt, ./jko0001.txt)
rename(./0002 jko0002.txt, ./jko0002.txt)

顺便说一句,在解决这样的问题时,有时将echo放在Problem命令前面会很有帮助,以了解传递给它的参数是什么:

$ find . -type f -name '*.txt' -print0 | xargs -0 echo rename -n -- 's/^\d{4}\s+//' {} +
rename -n -- s/^\d{4}\s+// {} + ./0003 jko0003.txt ./0001 jko0001.txt ./0002 jko0002.txt
                           ^^^^ this is the problem

但这有时会产生误导,因为(在其他方面)它忽略了参数中的空格和空格between参数之间的区别.用printf '%q\n'替换echo有时会更好(尽管它有其他问题,并且并不是所有的外部printf实现都支持%q).

Linux相关问答推荐

无法在Raspberry PI 3 Model B上分配256TB的虚拟内存

Aarch64在Linux上是否有红色区域,如果有,是16个字节还是128个字节?

如何注释掉SLURM中的延迟调度命令?

Bash:将多行转换为单行的命令

计算与文件第一列对应的第二列中的字符串出现次数

不带空格的字符串连接形成文件路径

如何在 DolphinDB 中递归查找目录中的所有文件?

用户级线程如何与内核级线程对话

anon 对 pmap 意味着什么?

我在哪里放置第三方库来设置 C++ Linux 开发环境?

为什么这个命令会杀死我的 shell?

如何以另一个用户的身份使用 sudo 在 bash 子shell 中执行一系列命令?

如何让 GNU 屏幕读取 .bash_profile/.bash_rc 更改?

'&&' 与 '&' 与 Bash 中的 'test' 命令

何时使用管道与何时使用共享内存

如何对 /dev/random 或 /dev/urandom 进行 base64 编码?

ImportError:在 ubuntu 14.04 中没有名为 _io 的模块

CentOS:在 PHP 安装中启用 GD 支持

如何在 Linux 中将 .so 文件添加到 java.library.path

在我的 index.php 中加载 CSS 和 JS 等资源时出现错误 403