使用 bash 更正文件编号

Posted

技术标签:

【中文标题】使用 bash 更正文件编号【英文标题】:Correcting file numbers using bash 【发布时间】:2017-05-08 00:42:03 【问题描述】:

我在这样的文件夹中有一堆文件名:

test_07_ds.csv
test_08_ds.csv
test_09_ds.csv
test_10_ds.csv
...

我想减少每个文件的数量,使它们变成:

test_01_ds.csv
test_02_ds.csv
test_03_ds.csv
test_04_ds.csv
...

这是我想出的:

for i in $1/*; do
    n=$i//[^0-9]/;
    n2=`expr $n - 6`;
    if [ $n2 -lt 10 ]; then
        n2="0"$n2;
    fi
    n3=`echo $i | sed -r "s/[0-9]+/$n2/"`
    echo $n3;
    cp $i "fix/$n3";
done;

有没有更清洁的方法?

【问题讨论】:

如果您有基于 perl 的重命名命令,请尝试 rename -n 's/\d+/sprintf "%02d", $&-6/e' test_* ... -n 选项用于试运行。如果发生冲突,它可能会抱怨已经存在的文件,但如果 @ 应该可以工作987654326@是自动版本排序的,给定的数字都是两位数 【参考方案1】:

这可能会有所帮助:

shopt -s extglob
for i in test_07..10_ds.csv; do
    IFS=_ read s m e <<<"$i";         # echo "Start=$s Middle=$m End=$e"
    n=$m#+(0)                       # Remove leading zeros to
                                      # avoid interpretation as octal number.
    n=$((n-6))                        # Subtract 6.
    n=$(printf '%02d' "$n")           # Format `n` with a leading 0.
    # comment out the next echo to actually execute the copy.
    echo \
        cp "$i" "fix/$s_$n_$e";
done;

或将它们全部折叠在一起

#!/bin/bash
shopt -s extglob
for i in $1:-./*; do                    # $1 will default to pwd `.`
    IFS=_ read s m e <<<"$i";             # echo "Start=$s Middle=$m End=$e"
    n=$(printf '%02d' "$(($m#+(0)-6))")
    cp "$i" "fix/$s_$n_$e";
done;

【讨论】:

要在变量可能以零开头时强制以 10 为基数,您还可以使用 var=010; echo $(( 10#$var ))。请注意,在这种情况下,$(()) 中的 $ 是必需的。 @BenjaminW。是的,而且(几乎)是正确的。试试:a='0006 + 2*3&lt;&lt;6'; echo $((10#$a))。任何真正的十进制整数都不应包含+*&lt;。解析整数并不是那么简单。 @BenjaminW。我应该添加一个n=$m//[^0-9] 作为第一个过滤器,但我无法解释为什么实际需要它的所有细节。 当然,它无法为您解析和清理表达式。我只是想把它作为$m#+(0) 的替代品。 @BenjaminW。是的,我明白了。 $((10#$a)) 删除零(如果这是要解决的一个问题),但它不能很好地与其他附加过滤器集成(如果需要)。一旦使用算术扩展,变量的处理就会结束。过滤为文本有助于执行额外的清理步骤。考虑到这一点,我相信它应该是清除变量值前面的零的首选方法。这就是我在这里使用它的原因。【参考方案2】:

您可以使用awk 进行简化:

for f in *.csv; do
   mv "$f" $(awk 'BEGINFS=OFS="_" $2 = sprintf("%02d", $2-6) 1' <<< "$f")
done

【讨论】:

啊,使用_ 作为 awk 分隔符,太好了!【参考方案3】:

您能否尝试以下代码,如果这对您有帮助,请告诉我。

awk 'FNR==1OLD=FILENAME;split(FILENAME, A,"_");A[2]=A[2]-6;NEW=A[1]"_"A[2]"_"A[3];system("mv " OLD " " NEW);close(OLD)' *.csv

我还假设您的文件总是从 _7 名称开始,所以我从每个名称中扣除了 6 个,以防您可以在 mv 命令中放置完整路径,该命令位于系统 awk 的内置实用程序和也可以将文件移动到另一个地方。让我知道情况如何。

【讨论】:

这正是@anubhava 正在做的事情,不过+1 表示努力!

以上是关于使用 bash 更正文件编号的主要内容,如果未能解决你的问题,请参考以下文章

bash脚本编程之数组及随机变量

01BASH基本操作

如何冲销凭证

linux学习第二周;shell编程

bash中的数组

在sql数据库,我插入一条数据有误,编号错了,和前面的重复,要怎么修改呢?