![批量重命名,在文件名的第 3 个位置递归添加额外的“。”字符](https://linux22.com/image/869957/%E6%89%B9%E9%87%8F%E9%87%8D%E5%91%BD%E5%90%8D%EF%BC%8C%E5%9C%A8%E6%96%87%E4%BB%B6%E5%90%8D%E7%9A%84%E7%AC%AC%203%20%E4%B8%AA%E4%BD%8D%E7%BD%AE%E9%80%92%E5%BD%92%E6%B7%BB%E5%8A%A0%E9%A2%9D%E5%A4%96%E7%9A%84%E2%80%9C%E3%80%82%E2%80%9D%E5%AD%97%E7%AC%A6.png)
我一直在努力让这个工作,但我不太擅长正则表达式。这是我尝试做的,但没有成功(50 分钟后,仍然没有明显的变化):
while IFS= read -r -d '' file; do mv $file ${file:0:2}.${file:2}; done
提前致谢!
答案1
在递归重命名目录中的文件时,您将不得不面对的一个问题是将文件名(您要修改的文件名)与路径分开。您不能简单地删除路径部分,因为这样您的文件最终将被移动,而不是简单地重命名。
要使用你原来的方法,我认为你需要做类似的事情
while read -r -d '' f; do
file="${f##*/}"; path="${f%/*}"
echo mv -- "$path/$file" "$path/${file:0:2}"."${file:2}"
done < <(find -type f -iname "*.wav" -print0)
另一个选择是使用find
命令的-execdir
而不是-exec
。我思考可以安全地假设结果将以仅以前导路径的形式呈现到您的重命名命令中(无论您使用rename
或),在这种情况下您可以执行mv
./
find -type f -iname "*.wav" -execdir rename -nv -- 's|\./..|$&.|' {} +
或者使用更像 perl 的变体
find -type f -iname "*.wav" -execdir rename -nv -- 's|\./..\K|.|' {} +
或者使用与原始mv
方法更等同的方法
find -type f -iname "*.wav" -execdir bash -c 'echo mv -- "$0" "${0:0:4}"."${0:4}"' {} \;
(请注意,子字符串索引已增加 2 以允许前导./
路径组件)。
如果您的版本find
没有该-execdir
选项,您可以修改rename
正则表达式以跳过最长匹配路径前缀,例如
find -type f -iname "*.wav" -exec rename -nv -- 's|.*/..\K|.|' {} +
注意:这些表达式中都有“无操作”开关(重命名的-n
选项或echo
命令),以便您可以验证它们会先做后承诺。
答案2
使用以下方法可以轻松完成rename
:
rename 's/ /\./' file.txt
例子:
$ ls -l
-rw-rw-r-- 1 user user 0 Mar 30 04:22 01 Song Title.flac
$ rename 's/ /\./' 01\ Song\ Title.flac
$ ls -l
-rw-rw-r-- 1 user user 0 Mar 30 04:22 01.Song Title.flac
编辑:如果你想在后面加一个空格01.
:
rename 's/ /\. /' file.txt
如果您希望目录下/directory/to/search
及其所有子目录下的所有文件的扩展.wav
名都按预期重命名,请尝试以下操作:
find /directory/to/search -type f -name "*.wav" -execdir rename 's/(^\d+) /$1. /' {} +
要不区分大小写:
find /directory/to/search -type f -iname "*.wav" -execdir rename 's/(^\d+) /$1. /' {} +
答案3
这有效(已测试):
#!/bin/bash
filenames=$(find . -type f) # stores all filenames in $filenames
for filename in $filenames; do # for each member in $filenames
newfilename=$(echo "$filename" | sed 's/\(.*\)\/\(..\)\(.*\)$/\1\/\2\.\3/') # edits $filename by adding a . after the second character and stores the edited string in $newfilename
mv "$filename" "$newfilename" # renames $filename to $newfilename
done