使用bash

时间:2016-12-22 11:37:42

标签: regex bash sed rename filenames

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

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;

有更清洁的方法吗?

3 个答案:

答案 0 :(得分:2)

这可能会有所帮助:

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;

答案 1 :(得分:1)

您可以使用awk进行简化:

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

答案 2 :(得分:1)

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

awk 'FNR==1{OLD=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的内置实用程序中也可以将文件移动到另一个地方。让我知道它是怎么回事。