重命名多个文件以减少文件名中的数字?

重命名多个文件以减少文件名中的数字?

我的文件命名不正确,但 -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. 将要重命名的文件移动到子目录中(不更改其名称)。
  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_805754DBGC180_805753...55to...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...96findsortxargs$HOME/bin/waltinatorman 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 语句,并使用其返回值作为替换文本。
  • -vrenameecho 执行它正在做的事情。

如果您想更加安全,请使用该标志-n,这样它rename只会告诉您它将做什么,而不是执行它。

这似乎只适用于递减,因此请小心处理。

相关内容