简体   繁体   English

在Bash中按顺序移动文件

[英]Move Files in Sequence in Bash

I'm trying to move folders from 1 to 05 and assigning numbers to them. 我正在尝试将文件夹从1移动到05并为它们分配数字。

Example: 例:

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

I've tried this; 我试过这个;

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

using it like this; 像这样使用它;

./script.sh 2 21 25

but I'm getting output; 但我得到了输出;

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

which is of course wrong, see example :-) 这当然是错的,见例子:-)

I've also tried it this way; 我也是这样试过的;

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

But I'm getting repeated output like this; 但是我会像这样重复输出;

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

Try using awk 尝试使用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  }'

Test 测试

$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

Nice looking multi-line code on OP's request 在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
}'

Now actual script for moving files 现在用于移动文件的实际脚本

#!/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);
  }
}'
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

From all the funny discussions we had in the comments (that was a really funny thread), I more or less (probably less ) understood what you want... or rather, I made my own idea of what I believe you want. 从我们在评论中所做的所有有趣的讨论(这是一个非常有趣的线索),我或多或少(可能更少 )理解你想要的东西......或者更确切地说,我对我认为你想要的东西有自己的想法。 Let me rephrase what I understood (and please forgive me if this is not what you exactly requested). 让我重新理解我的理解(如果这不是你要求的话,请原谅我)。

You want a script that will take three non-negative numeric arguments X , Y and Z (with possibly leading 0 's) with X<Y and you want to output test-M => test-N where: 你想要一个脚本,它将采用X<Y三个非负数字参数XYZ (可能前导0 )并且你想输出test-M => test-N ,其中:

  • M ranges from X to Y , left-padded with 0 's so that the number of characters in M is the max number of characters in X and Y M范围从XY ,左边用0填充,因此M中的字符数是XY的最大字符数
  • N=M+Z , left-padded with 0 's so that the number of characters in N is the max number of characters of X , Y , Z and Y+Z . N=M+Z ,左边填充为0 ,因此N中的字符数是XYZY+Z的最大字符数。 Eg, 例如,

     $ ./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 

Also, you want a bash solution so that you can mv the corresponding files without needing to parse the output of another command. 此外,您需要一个bash解决方案,以便您可以mv相应的文件,而无需解析另一个命令的输出。

Here we go, and hopefully you'll find some interesting stuff to dig too (remark, the output is of the form mv -nv xxx yyy rather than test-x => test-y ; remove the echo when you're happy with this): 我们走了,希望你能找到一些有趣的东西来挖掘(注意,输出的形式是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

I've added the variables prepend_source , append_source , prepend_target , append_target at the beginning of the script so that you can replace them easily by what you want. 我在脚本的开头添加了变量prepend_sourceappend_sourceprepend_targetappend_target ,以便您可以根据需要轻松替换它们。 You could add option parsings to be able to set them from the command line (left as an exercise, unless you insist I do it for you). 你可以添加选项解析,以便能够从命令行设置它们(左边作为练习,除非你坚持我为你做这个)。

Caveat. 警告。 The numbers are directly handled by bash, so you must use them from within bash's arithmetic range which is (very likely) on a 64 bits machine: [-9223372036854775808,9223372036854775807]. 这些数字直接由bash处理,因此你必须在bash的算术范围内使用它们(非常可能)在64位机器上:[ - 9223372036854775808,9223372036854775807]。 So there's a lot you can do before reaching that. 所以在达到目标之前你可以做很多事情。 Now, don't worry, the script will not break if anything goes outside this range because I added explicit checks. 现在,不要担心,如果超出此范围,脚本将不会中断,因为我添加了显式检查。 If this is truly a limitation, you can always use bc or dc instead. 如果这确实是一个限制,您可以始终使用bcdc The bc or dc implementation is left to the reader as an exercise. bcdc实现作为练习留给读者。 By the way, this only works with non-negative integers . 顺便说一句,这只适用于非负整数


Is your solution as robust and general as this one? 您的解决方案是否像这一样强大而通用?

You only need one loop. 你只需要一个循环。 But whichever way you count it, the number you use for one purpose is going to be the wrong number for the other purpose. 但无论你怎么计算它,你用于一个目的的数字对于另一个目的而言将是错误的数字。 So you need to use arithmetic to get the right number, eg: 所以你需要使用算术来得到正确的数字,例如:

$(( $num + 220 ))

Here is what I have so far; 这是我到目前为止所拥有的;

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

output I get by running ./script.sh 01 05 220 通过运行./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

so it looks like it matches my example :-) 所以看起来它符合我的例子:-)

Thanks to all your guys help this is what I have now; 感谢你们所有人的帮助,这就是我现在所拥有的;

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

and this is the output I get when I run ./script.sh 01 10 220 for example; 这是我运行时获得的输出./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

This was exactly what I wanted to achieve. 这正是我想要实现的目标。 Thanks a lot to "Robin Green" and "gniourf_gniourf". 非常感谢“Robin Green”和“gniourf_gniourf”。

and now moving of directories work correctly ^_^ 现在移动目录正常工作^ _ ^

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

output of moved directories is; 移动目录的输出是;

‘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’

Problem only occurs when I run; 问题只发生在我跑步时; ./script.sh 01 10 0 this is the output I get; ./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

as you can see no leading zeros =( 你可以看到没有前导零=(

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM