![重命名多个文件以减少文件名中的数字?](https://linux22.com/image/95359/%E9%87%8D%E5%91%BD%E5%90%8D%E5%A4%9A%E4%B8%AA%E6%96%87%E4%BB%B6%E4%BB%A5%E5%87%8F%E5%B0%91%E6%96%87%E4%BB%B6%E5%90%8D%E4%B8%AD%E7%9A%84%E6%95%B0%E5%AD%97%EF%BC%9F.png)
我的文件命名不正确,但 -1 未同步。问题是我需要重命名其中的数千个。
- DBGC180_805754
- DBGC180_805755
- DBGC180_805756
到
- DBGC180_805753
- DBGC180_805754
- DBGC180_805755
我更喜欢使用 bash 脚本或 unix 命令。
答案1
你可以这样做:
# {smallestfilenum..largestfilenum}
for i in {805754..999999}; do
mv "DBGC180_$i" "DBGC180_$(($i-1))";
done
使用较小的数字(例如 805754..805758)进行尝试,以确保它按您的预期工作。请注意,如果具有新名称的文件已存在,它将被覆盖。
答案2
- 将要重命名的文件移动到子目录中(不更改其名称)。
- 将子目录中的文件重命名到原始目录中。
我推荐步骤 1 有两个原因,即使没有它也是可能的:
- 如果命令被中断,您可以从上次中断的地方继续,因为哪些文件已被重命名、哪些文件尚未重命名是显而易见的。
- 您无需担心以错误的顺序重命名并覆盖现有文件之一。
未经测试的 shell 片段(依赖于要递减的数字永远不会有任何前导零的事实):
mkdir to_decrement
for x in DBGC180_80575[4-9] DBGC180_8057[6-9]? DBGC180_805[8-9]?? DBGC180_80[6-9]??? DBGC180_8[1-9]???? DBGC180_9?????; do
mv "$x" to_decrement/
done
cd to_decrement
for x in *; do
number="${x##*_}"
mv -i -- "$x" "../${x%_*}_$((number-1))"
done
cd ..
rmdir to_decrement
和桀骜,你可以让这变得更简单,这要归功于它数字范围全局, 它是内置mv
这避免了遇到命令行长度限制,及其基于模式的批量重命名功能。在 zsh 中:
autoload -U zmv
zmodload -m -F zsh/files b:zf_\*
mkdir to_decrement
zf_mv DBGC180_<805754-> to_decrement/
zmv 'to_decrement/(*)_(*)' '${1}_$(($2-1))'
rmdir to_decrement
答案3
因此,您想要重命名DBGC180_805754
为DBGC180_805753
、...55
to...54
等等。这就是我要解决的问题。
首先,将此脚本放在您的某个位置PATH
,调用它waltinator
。
#!/bin/bash
#step through the parameters
while [[ -n "$1" ]] ; do
oldname="$1"
# shift the arguments left
shift;
# strip off the fixed part of the old name
oldnum=${oldname##DBGC180_}
# decrement the number (this is what was wanted, right?)
newnum=$(( $oldnum - 1 ))
# build the new, improved filename
newname="DBGC180_$newnum"
if [[ -f "$newname" ]] ; then
printf "Cannot rename $oldname to $newname, $newname exists.\n" >&2
exit 1
fi
mv --no-clobber "$oldname" "$newname"
done
exit 0
对于下一步,假设脚本位于 中$HOME/bin/waltinator
,并且您有 does chmod +x $HOME/bin/waltinator
。
find . -type f -name 'BDGC180_[0-9][0-9][0-9][0-9][0-9][0-9]` -print | \
sort | \
xargs $HOME/bin/waltinator
查找find
文件(无特定顺序),其名称与 shell glob 模式“BDGC180_
后跟 6 位数字 ( ) 匹配。由于我们需要一个排序列表(在重命名之前重命名为[0-9]
会失败),因此我们运行through的输出。然后,如果需要缩短参数列表,我们将获取(排序的)文件名列表,并构建一个命令将(排序的)文件名列表传递给Read 。...97
...96
...96
find
sort
xargs
$HOME/bin/waltinator
man xargs
为此,请阅读:
for page in bash mv find sort xargs ; do
man "$page"
done
答案4
用于rename
将每个数字替换为自身减 1。
$ rename -v 's/\d{6}/sprintf("%06",($&-1))/e'
笔记
rename
使用 Perl 表达式来重命名文件名。s
指定rename
将替换部分或全部与正则表达式模式匹配的文件名。- Perl 替换表达式的结构如下。
s/PATTERN/REPLACEMENT/MODIFIER
\d{6}
rename
是将搜索和替换的模式。这是 6 位小数。$
是存储匹配的子字符串的变量\d{6}
(在本例中“子字符串”是一个 int)。sprintf("%06",($&-1))
检索存储在 中的值$
,将其递减,然后返回该值作为替换值。是%06
用来处理前导零的。e
指定rename
将替换计算为 Perl 语句,并使用其返回值作为替换文本。-v
让rename
echo 执行它正在做的事情。
如果您想更加安全,请使用该标志-n
,这样它rename
只会告诉您它将做什么,而不是执行它。
这似乎只适用于递减,因此请小心处理。