在文件名中向个位数添加 0

在文件名中向个位数添加 0

这些是我的示例文件

user@linux:~$ ls -l | cut -d ' ' -f 10-

ch 10 - file.txt
ch 2 - file.txt
ch 3 - file.txt
ch 4a - file.txt
ch 5 - file.txt
user@linux:~$ 

我想添加0到任何单个数字(包括4a),所以最终的输出将是这样的。

user@linux:~$ ls -l | cut -d ' ' -f 10-

ch 10 - file.txt
ch 02 - file.txt
ch 03 - file.txt
ch 04a - file.txt
ch 05 - file.txt
user@linux:~$ 

使用 Linux 中的内置工具可以实现这一点吗?

答案1

图案

'ch '[1-9][!0-9]*'- file.txt'

将匹配所有需要更改的文件名(在您显示的文件名之外),即以 开头的任何文件名ch ,后跟 1 到 9 之间的数字,后跟非数字的内容。之后,我们允许使用任何字符,并且名称必须以 结尾- file.txt

我们可以循环这些文件

for name in 'ch '[1-9][!0-9]*'- file.txt'; do
    ...
done

现在的目标是0在该位之后插入一个ch 。这可以通过剥离子ch 字符串并将其替换为ch 0

for name in 'ch '[1-9][!0-9]*'- file.txt'; do
    newname='ch 0'${name#ch }
done

参数${name#ch }替换将扩展为2 - file.txtif $namecontains ch 2 - file.txt(它将删除前缀ch )。

之后,您可以重命名该文件:

for name in 'ch '[1-9][!0-9]*'- file.txt'; do
    newname='ch 0'${name#ch }

    printf 'would rename "%s" into "%s"\n' "$name" "$newname"
    # mv -i "$name" "$newname"
done

运行一次循环后,删除#带有注释掉的mv命令的行,看看它是否做了正确的事情。

上面的循环,给定您显示的文件名,将输出

would rename "ch 2 - file.txt" into "ch 02 - file.txt"
would rename "ch 3 - file.txt" into "ch 03 - file.txt"
would rename "ch 4a - file.txt" into "ch 04a - file.txt"
would rename "ch 5 - file.txt" into "ch 05 - file.txt"

答案2

使用 Lary Wall 的rename/ prenamerename在 Debian/Ubuntu 中,prename在 RedHat/Fedora 中):

rename -n 's/^ch (\d) /ch 0$1 /' *

-n用于空运行,删除(或用“-v”替换)以进行实际执行。

答案3

zsh

autoload zmv # best in .zshrc
zmv -n '*[0-9]*' '${f//(#m)<->/${(l:2::0:)MATCH}}'

-n如果满意,请删除(试运行))。

l所有数字 ef-pad 至宽度 2。

也当心它截断宽度为 2 的数字(将变为1234-2.txt34-02.txt

不确定你的意思内置,特别是关于Linux这只是一个内核。autoload是 zsh 内置函数,但请注意,zmv可自动加载函数会调用mv默认情况下不是内置函数的实用程序(但可以使用 使其成为内置函数zmodload zsh/files)。

答案4

这就是您正在寻找的。

需要做的事情基本上有以下几点:

1、检查数字是个位数还是两位数。如果是个位数且值小于或等于9,则重命名该文件。这应该像这样做一样简单:

(( someDigit <= 9 )) && [[ ${#someDigit'slength} -lt 2 ]]

2、由于会有一些带有字母的文件,所以我们可以将它们存储为:

digit=$( echo $file | cut -d '-' -f1 | grep ch | awk '{print $2}' );

3、然后过滤数字,以便我们可以将其与第一个选项进行比较。添加更多您可能认为在选项中必要的过滤器,tr -d如下所示:

digitOnly=$( echo $digit | tr -d [a-Z] );  

4、然后在要重命名文件的目录中运行循环。实现所有这些将如下所示:

for file in *file.txt; do
  digit=$( echo $file | cut -d '-' -f1 | grep ch | awk '{print $2}' );
  digitOnly=$( echo $digit | tr -d [a-Z] );
  if (( digitOnly <= 9 )) && [[ ${#digitOnly} -lt 2 ]]; then
    # mv "${file}" "ch 0${digit} - file.txt"
    echo "'${file}' is renamed to 'ch 0${digit} - file.txt'";
  fi
done

把mv中的#去掉,满意后再真正执行。以你的例子:

touch 'ch 10 - file.txt' 'ch 2 - file.txt' 'ch 3 - file.txt' 'ch 4a - file.txt' 'ch 5 - file.txt'

然后,执行脚本或复制粘贴上面的内容scriptbash给出以下输出:

'ch 2 - file.txt' is renamed to 'ch 02 - file.txt'
'ch 3 - file.txt' is renamed to 'ch 03 - file.txt'
'ch 4a - file.txt' is renamed to 'ch 04a - file.txt'
'ch 5 - file.txt' is renamed to 'ch 05 - file.txt'

显然,您甚至可以使其更加通用,方法是将其包含在函数中,然后接受文件模式搜索等输入,但您的问题并不要求这样做。因此,我相信当前的答案可以很好地处理问题中所述的情况。

相关内容