在Unix中基于模式重命名多个文件

330

目录中有多个以前缀fgh开头的文件,例如:

fghfilea
fghfileb
fghfilec

我想将它们所有重命名为以前缀 jkl 开头。是否有一种单个命令可以代替逐个重命名每个文件?


2
请在此处查看:http://theunixshell.blogspot.com/2013/01/bulk-renaming-of-files-in-unix.html - Vijay
相关问题:基于多个模式重命名文件的更好方法 - Michaël Le Barbier
26个回答

0

使用正则表达式,这对我很有效:

我想要将文件重命名为这样:

file0001.txt -> 1.txt
ofile0002.txt -> 2.txt 
f_i_l_e0003.txt -> 3.txt

使用正则表达式[a-z|_]+0*([0-9]+.),其中([0-9]+.)是一个分组子字符串,可用于重命名命令。

ls -1 | awk 'match($0, /[a-z|\_]+0*([0-9]+.*)/, arr) { print   arr[0]  " "  arr[1] }'|xargs  -l mv

生成:

mv file0001.txt 1.txt
mv ofile0002.txt 2.txt
mv f_i_l_e0003.txt 3.txt

另一个例子:
file001abc.txt -> abc1.txt
ofile0002abcd.txt -> abcd2.txt 

ls -1 | awk 'match($0, /[a-z|\_]+0*([0-9]+.*)([a-z]+)/, arr) { print   arr[0]  " "  arr[2] arr[1] }'|xargs  -l mv

生成:

  mv file001abc.txt abc1.txt
  mv ofile0002abcd.txt abcd2.txt 

警告,小心。


0
我编写了这个脚本,用于递归搜索所有的 .mkv 文件并将找到的文件重命名为 .avi。您可以根据自己的需求进行定制。我还添加了一些其他功能,例如从文件路径中获取文件目录、扩展名和文件名,以防将来需要引用某些内容。
find . -type f -name "*.mkv" | while read fp; do 
fd=$(dirname "${fp}");
fn=$(basename "${fp}");
ext="${fn##*.}";
f="${fn%.*}";
new_fp="${fd}/${f}.avi"
mv -v "$fp" "$new_fp" 
done;

0
这个答案只是其他答案中所解释的内容的具体应用,希望对你有用:
我遇到了一个情况,需要将一些以CodeAPE_fr.properties形式命名的属性文件重命名为CodeAPE.properties,并且是在整个目录中进行操作,我做了以下操作:
for i in `dir`; do mv $i `echo $i | sed 's/_fr.properties/.properties/g'`; done

0
如果文件名中有空格,并且您想根据文件名中具有空格的部分进行过滤,这里有一个轻微的改进/调整需要做:
for f in "Filename With Spaces"*; do mv "$f" "$(echo $f | sed 's/^Filename With Spaces/FilenameWithNoMoreSpaces/g')"; done

我的答案的关键区别在于,如果你想要使用文件名中的"Filename With Spaces"作为筛选条件来选择要操作的文件,你需要在其周围加上引号。之前的答案提到了带有空格的文件名,但是选择的文件是基于jkl*,而不是带有空格的文件名。
注意:你不必用FilenameWithNoMoreSpaces替换。我只是想以一个典型的用例作为示例。
如果文件名中的空格模式位于文件名的中间,则调整后的命令将遵循以下模式:
for f in *"Spaces In Middle of Filename"*; do mv "$f" "$(echo $f | sed 's/Spaces In Middle of Filename/FilenameWithNoMoreSpaces/g')"; done

注意,我在文件名模式的开头添加了另一个带有空格的星号,并从sed命令的“查找”部分中删除了插入符号^。如果我解释得太多,我向你道歉。我考虑到有些人可能对编程完全陌生。

0

您也可以使用以下脚本。在终端上运行非常容易...

//同时重命名多个文件

for file in  FILE_NAME*
do
    mv -i "${file}" "${file/FILE_NAME/RENAMED_FILE_NAME}"
done

例子:

for file in  hello*
do
    mv -i "${file}" "${file/hello/JAISHREE}"
done

0

这是find + sed + xargs解决方案的扩展版本。

原始解决方案:thisthis

要求:搜索、修剪、正则表达式、重命名

  1. 我想在许多文件夹中重命名多个文件。
  2. 有些文件夹应该被修剪/排除。
  3. 我使用的是cygwin,无法使所需的perl rename工作,这是最流行的解决方案(而且我认为它很慢,因为它似乎没有修剪选项?)

解决方案

  1. 使用find有效地获取文件(带修剪),并具有许多自定义选项。
  2. 使用sed进行正则表达式替换。
  3. 使用xargs将结果导入最终命令。

示例1:重命名*.js文件但忽略node_modules

此示例查找文件并显示找到的文件和重命名后的文件。出于安全原因,它现在不会移动任何内容。您必须将echo替换为mv

set -x # stop on error
set -e # verbose mode (echo all commands)

find "." -type f -not \( -path "**/node_modules/**" -prune \) -name "*.js" | 
  sed -nE "s/(.*)\/my(.*)/& \1\/YOUR\2/p" |
  xargs -n 2 echo  # echo first (replace with `mv` later)

上述脚本将其转换为:

./x/y/my-abc.js

变成这样:

./x/y/YOUR-abc.js

解决方案的分解

找出所有后缀为 ".js" 的文件:`find "." -type f -not \( -path "**/node_modules/**" -prune \) -name "*.js"`
说明:
  • 查找文件(`-type f`)。
  • `-not` 排除 `node_modules` 文件夹(不会遍历此文件夹)。
  • 文件名必须匹配 `*.js`。
  • 您可以添加更多的包含和排除条件。
  • 参考链接:
    • 本文讨论了递归查找文件的替代方法。
    • 本文讨论了修剪和排除的方面。
    • man find
将文件名中的 "my-" 替换为 "YOUR-":`sed -nE "s/(.*)\/my\-(.*\.js)/& \1\/YOUR-\2/p"`
说明:
  • 注意:要掌握 `sed` 总是需要一些时间。
  • `-E` 启用“扩展”(即更现代化的)正则表达式语法。
  • `-n` 与尾随的 `/p` 标志一起使用:`-n` 隐藏所有结果,而 `/p` 只打印匹配的结果。这样,我们只看到/移动需要更改的文件,而忽略所有其他文件。
  • 替换正则表达式的格式始终为:`s/regex/replacement/FLAGS`
  • 在替换中,`&` 表示匹配的输入字符串。这是 `mv` 的第一个参数。
  • 参考链接:
运行命令 `echo` 并使用替换后的字符串的前两个字符串:`xargs -n 2 echo`
说明:
  • 使用(替换后字符串的)前两个字符串运行 `echo` 命令。
  • 参考链接:man xargs

祝你好运!


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接