在Bash中按顺序移动文件

时间:2013-11-10 13:24:35

标签: bash

我正在尝试将文件夹从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

6 个答案:

答案 0 :(得分: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);
  }
}'

答案 1 :(得分: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

答案 2 :(得分:1)

从我们在评论中提到的所有有趣的讨论(这是一个非常有趣的主题),我或多或少(可能)理解你想要的东西......或者说,我做了我的我自己的想法,我相信你想要的。让我重新理解我理解的内容(如果这不是你要求的话,请原谅我。)

你想要一个脚本,它会带有三个非负数字参数XYZ(可能带领0)和{{1}并且您想要输出X<Y其中:

  • test-M => test-N的范围从MX,左边填充Y,以便0中的字符数是最大数量MX
  • 中的字符
  • Y,左侧填充N=M+Z个,以便0中的字符数是N的最大字符数,{{ 1}},XY。如,

    Z

此外,您需要一个bash解决方案,以便您可以Y+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 而不是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_sourceappend_source,以便您可以根据需要轻松替换它们。你可以添加选项解析,以便能够从命令行设置它们(左边作为练习,除非你坚持我为你做这个)。

[-9223372036854775808,9223372036854775807]:

<强>买者的数字直接由bash的64位机器上处理的,所以必须从它是(很可能)bash的算术范围内使用它们。所以在达到目标之前你可以做很多事情。现在,不要担心,如果超出此范围,脚本将不会中断,因为我添加了显式检查。如果这确实是一个限制,您可以随时使用prepend_targetappend_targetbcdc实施作为练习留给读者。顺便说一句,这只适用于非负整数


您的解决方案是否与此一样强大且通用?

答案 3 :(得分:0)

你只需要一个循环。但无论你怎么计算它,你用于一个目的的数字对于另一个目的而言将是错误的数字。因此,您需要使用算术来获得正确的数字,例如:

$(( $num + 220 ))

答案 4 :(得分: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

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

答案 5 :(得分: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

因为你看不到前导零=(