我的目录中有很多名为“bar_foo.txt”的文件,我想将它们重命名为“foo_bar.txt”。
在 中sed
,vim
其正则表达式类似于's/\(bar\)_\(foo\)/\2_\1/g'
,在替换中反向引用搜索。
有没有办法做到这一点
rename
?我见过一些黑客通过管道传输ls
到sed
tobash
,但这显然不是一个令人惊奇的方法。还有其他工具可以做到这一点吗?
正则表达式的“sed 和 vim 风格”有名称吗?
答案1
如果您rename
使用 Perl 正则表达式实现(如在 Debian/Ubuntu/... 或prename
Arch Linux 上),则需要$1
而不是\1
.另外,捕获括号时没有反斜杠:
rename 's/(.*)_(.*)/$2_$1/' *_*
如果没有,您必须自己实施。
#! /bin/bash
for file in *_* ; do
left=${file%_*}
right=${file##*_}
mv "$file" "$right"_"$left"
done
注意:正如所写,两个命令都重命名a_b_c
为c_a_b
.要获取b_c_a
,请将第一个捕获组更改为.*?
(在第一种情况下),或在第二种情况下将第一个捕获组更改%
为%%
和##
to 。#
答案2
执行此操作的标准工具是pax
- 尽管它使用硬链接和副本比直接移动效果更好。当然,所有的举动本质上都是创建一个新链接并删除一个旧链接。
我更喜欢脱离这些步骤——暂时我有同一棵树的两个副本,可以进行比较和对比。这在动态重命名文件时尤其重要 - 对文件名进行编辑操作的结果可能与现有链接名相同,在这种情况下哪个文件获取该名称?
因此,要按照 POSIXly 的要求做这件事,你可以这样做:
pax -rwls'|^\(bar\)_\(foo\).txt$|\2_\1.txt|' -s'|.*||' *_*.txt .
当您完成后,结果将是指向相关文件的单独链接。验证结果是否符合您的要求并删除旧的。
并且sed
,vim
正则表达式样式是标准的布雷
答案3
随着实用程序Linux
rename
,不,这个只做基本的字符串替换。对于基于 Perl 的rename
,是的,请参阅乔罗巴的回答。使用 zsh 的
zmv
:autoload -U zmv # put this in your ~/.zshrc zmv '(*)_(*).(*)' '${2}_$1.$3' zmv -w '*_*.*' '${2}_$1.$3'
上面的两个
zmv
调用是等效的。要在子目录中执行操作,您可以使用zmv -w '**/*_*.*' '$1/${3}_$2.$4'
Vi(m)和sed的使用(扩展)基本正则表达式。也可以看看为什么我的正则表达式在 X 中有效但在 Y 中无效?