1

我正在尝试将文件夹从 1 移动到 05 并为它们分配数字。

例子:

test-01 => test-221
test-02 => test-222
test-03 => test-223
test-04 => test-224
test-05 => test-225

我试过这个;

for num in $(seq -w $2 $3); {
  mv -v "test-$num" "test-$1$num"
}

像这样使用它;

./script.sh 2 21 25

但我得到了输出;

test-21 => test-221
test-22 => test-222
test-23 => test-223
test-24 => test-224
test-25 => test-225

这当然是错误的,请参见示例:-)

我也试过这种方式;

for a in {1..5}; {
  for b in {21..25}; {
    echo "$a => $b"
  } #b
} #a

但我得到这样的重复输出;

1 => 21
1 => 22
1 => 23
1 => 24
1 => 25
2 => 21
2 => 22
2 => 23
2 => 24
2 => 25
3 => 21
3 => 22
3 => 23
3 => 24
3 => 25
4 => 21
4 => 22
4 => 23
4 => 24
4 => 25
5 => 21
5 => 22
5 => 23
5 => 24
5 => 25
4

6 回答 6

2

尝试使用awk

#!/bin/bash

awk -v fa=$1 -v fb=$2 -v ta=$3  'BEGIN {  for(i=fa;i<=fb;i++) printf "test-%02d => test-%02d\n",i,i+ta  }'

测试

$bash -f main.sh 1 5 220
test-01 => test-221
test-02 => test-222
test-03 => test-223
test-04 => test-224
test-05 => test-225

根据 OP 的要求,漂亮的多行代码

#!/bin/bash

awk -v fa=$1 -v fb=$2 -v ta=$3  'BEGIN {  
  for(i=fa;i<=fb;i++) 
    printf "test-%02d => test-%02d\n",i,i+ta
}'

现在用于移动文件的实际脚本

#!/bin/bash

awk -v fa=$1 -v fb=$2 -v ta=$3  'BEGIN {  
  for(i=fa;i<=fb;i++) {
    cmd = sprintf ("mv -v test-%02d test-%02d",i ,i+ta);
    # print cmd;
    system(cmd);
  }
}'
于 2013-11-10T13:57:03.217 回答
1
from_a=1
to_a=5
width_a=2
from_b=220
width_b=3
for a in $(seq $from_a $to_a); do
    printf -v file_a "%0"$width_a"d" "$a"
    printf -v file_b "%0"$width_b"d" $(($a + $from_b))
    echo "test-$file_a => test-$file_b"
done
于 2013-11-10T13:32:46.700 回答
1

从我们在评论中进行的所有有趣的讨论(那是一个非常有趣的话题),我或多或少(可能不太了解)你想要什么......或者更确切地说,我对我相信你想要什么有了自己的想法。让我重新表述一下我的理解(如果这不是您的确切要求,请原谅我)。

您需要一个脚本,该脚本将采用三个非负数字参数XY并且Z(可能带有前导0),X<Y并且您希望输出test-M => test-N其中:

  • M范围从X到,用'sY左填充,因此其中的字符数是和中的最大字符数0MXY
  • N=M+Z, 用 's 向左填充,0这样字符数就是,和的N最大字符数。例如,XYZY+Z

    $ ./script 01 04 00220
    test-01 => test-00221
    test-02 => test-00222
    test-03 => test-00223
    test-04 => test-00224
    
    $ ./script 99 101 0
    test-099 => test-099
    test-100 => test-100
    test-101 => test-101
    
    $ ./script 99 101 00000
    test-099 => test-00099
    test-100 => test-00100
    test-101 => test-00101
    
    $ ./script 00 02 99
    test-00 => test-099
    test-01 => test-100
    test-02 => test-101
    

此外,您需要一个 bash 解决方案,这样您就可以mv在不需要解析另一个命令的输出的情况下获取相应的文件。

我们开始吧,希望你也能找到一些有趣的东西来挖掘(注意,输出是表单mv -nv xxx yyy而不是;当你对此感到满意时test-x => test-y删除):echo

#!/bin/bash

prepend_source=test-
prepend_target=test-
append_source=
append_target=

shopt -s extglob

die() { printf >&2 "%s\n" "$@"; exit 1; }

is_number() { [[ $1 = +([[:digit:]]) ]]; }

is_in_range() { [[ -z ${1//0/} ]] || [[ ${1/#+(0)} = $((10#$1)) ]]; }

maxlength() {
    local u l=0 retvar=$1
    shift
    for i in "$@"; do
        u=${#i}
        ((u>l)) && ((l=u))
    done
    printf -v "$retvar" "%d" "$l"
}

X=$1
Y=$2
Z=$3

is_number "$X" || die "First argument is not a valid number"
is_number "$Y" || die "Second argument is not a valid number"
is_number "$Z" || die "Third argument is not a valid number"

(( 10#$X <= 10#$Y )) || die "Error: first argument is greater than second"

is_in_range "$X" || die "First argument out of range"
is_in_range "$Y" || die "Second argument out of range"
is_in_range "$Z" || die "Third argument out of range"
(( 10#$Y + 10#$Z >= 0 )) || die "Sum of second and last arguments is out of range"

maxlength "length_s" "$X" "$Y"
maxlength "length_t" "$X" "$Y" "$Z" "$((10#$Y+10#$Z))"

for ((i=10#$X;i<=10#$Y;++i)); do
    printf -v source "%s%.${length_s}d%s" "$prepend_source" "$i" "$append_source"
    printf -v target "%s%.${length_t}d%s" "$prepend_target" "$((10#$Z+$i))" "$append_target"
    # Here we're all done!
    echo mv -nv -- "$source" "$target" || die "Problem in mv" # or another error handle
done

我在脚本的开头添加了变量prepend_source, append_source, prepend_target,append_target以便您可以轻松地将它们替换为您想要的。您可以添加选项解析以便能够从命令行设置它们(留作练习,除非您坚持我为您做)。

警告。这些数字由 bash 直接处理,因此您必须在 bash 的算术范围内使用它们,这(很可能)在 64 位机器上:[-9223372036854775808,9223372036854775807]。所以在达到这个目标之前你可以做很多事情。现在,不用担心,如果超出此范围,脚本不会中断,因为我添加了显式检查。如果这确实是一个限制,您始终可以使用bcordc代替。bcordc实现留给读者作为练习。顺便说一句,这只适用于非负整数


您的解决方案是否像这个一样强大和通用?

于 2013-11-10T14:47:36.210 回答
0

你只需要一个循环。但无论你用哪种方式计算,你用于一个目的的数字将是另一个目的的错误数字。所以你需要使用算术来获得正确的数字,例如:

$(( $num + 220 ))
于 2013-11-10T13:31:01.147 回答
0

这是我到目前为止所拥有的;

for i in $(seq -w $1 $2); {
  echo "test-$i => test-$((i+$3))"
} #for

我通过运行 ./script.sh 01 05 220 得到的输出

test-01 => test-221
test-02 => test-222
test-03 => test-223
test-04 => test-224
test-05 => test-225

所以它看起来像我的例子:-)

于 2013-11-10T13:43:50.670 回答
0

感谢你们所有人的帮助,这就是我现在所拥有的;

for i in $(seq -w $1 $2); {
  echo "test-$i => test-$((10#$i+$3))"
} #for

例如,这是我运行 ./script.sh 01 10 220 时得到的输出;

test-01 => test-221
test-02 => test-222
test-03 => test-223
test-04 => test-224
test-05 => test-225
test-06 => test-226
test-07 => test-227
test-08 => test-228
test-09 => test-229
test-10 => test-230

这正是我想要实现的。非常感谢“Robin Green”和“gniourf_gniourf”。

现在目录的移动工作正常^_^

mv -v "temp/test-$i" "temp/test-$((10#$i+$3))"

移动目录的输出是;

‘temp/test-01’ -> ‘temp/test-221’
‘temp/test-02’ -> ‘temp/test-222’
‘temp/test-03’ -> ‘temp/test-223’
‘temp/test-04’ -> ‘temp/test-224’
‘temp/test-05’ -> ‘temp/test-225’
‘temp/test-06’ -> ‘temp/test-226’
‘temp/test-07’ -> ‘temp/test-227’
‘temp/test-08’ -> ‘temp/test-228’
‘temp/test-09’ -> ‘temp/test-229’
‘temp/test-10’ -> ‘temp/test-230’

问题仅在我运行时出现;./script.sh 01 10 0 这是我得到的输出;

test-01 => test-1
test-02 => test-2
test-03 => test-3
test-04 => test-4
test-05 => test-5
test-06 => test-6
test-07 => test-7
test-08 => test-8
test-09 => test-9
test-10 => test-10

如您所见,没有前导零=(

于 2013-11-10T13:54:26.613 回答