仅计算成功的移动尝试

时间:2019-01-13 13:47:36

标签: bash

问题是我无法弄清楚如何仅计算移动文件的“成功”尝试。

我的脚本将$ PATH中的目录作为目标,并尝试从指定目录中获取文件(直到该目录为空),以随机顺序将其随机排列,然后从$ PATH移至目录。

x=0
while [[ $(ls -A Directory/jpg | wc -l) -gt 0 ]]
do
  for i in "${destination[@]}"
  do
    shuf -zn1 -e Directory/jpg/*.jpg | xargs -0 mv -vt $i/somedir 2>/dev/null
    x=$((x + 1))
  done
done

我的“ x”计数器实际上大于“目录/ jpg”中的文件数量,我想“ x”仅表示复制的文件的确切数量。

2 个答案:

答案 0 :(得分:0)

我对脚本进行了一些修改以进行测试:

#!/bin/bash                                                                                                             
destination[0]=dest1
destination[1]=dest2
destination[2]=dest3
x=0
while [[ $(ls -A source | wc -l) -gt 0 ]]
do
  for i in "${destination[@]}"
  do
    shuf -zn1 -e source/* | xargs -0 mv -vt $i
    x=$((x + 1))
  done
done

echo $x

因此,在source中有三个目标目录和不同数量的文件时,我注意到x始终是destination数组中元素数量的倍数。

删除2>/dev/null发现了一个隐藏的问题:

... # other mv output
renamed 'source/file14' -> 'dest2/file14'
renamed 'source/file16' -> 'dest3/file16'
renamed 'source/file5' -> 'dest1/file5'
mv: cannot stat 'source/*': No such file or directory
mv: cannot stat 'source/*': No such file or directory

计算了最后两个失败的动作!

for i in "${destination[@]}"总是要循环播放等于destination数组中元素数量的次数。也就是说,如果destination具有三个元素,即使文件数量不多,循环也将始终使用i = 1i = 2i = 3执行。 for循环将始终将x中的元素数量增加destination。因此,x将大于移动的文件数。 (除非文件数是目标数组中元素数的倍数)

可以通过在for循环内部添加测试以检查是否存在更多要移动的文件来解决此问题:

#!/bin/bash                                                                                                             
destination[0]=dest1
destination[1]=dest2
destination[2]=dest3
x=0
while [[ $(ls -A source | wc -l) -gt 0 ]]
do
  for i in "${destination[@]}"
  do
    shuf -zn1 -e source/* | xargs -0 mv -vt $i
    x=$((x + 1))
    [[ $(ls -A source | wc -l) -eq 0 ]] && break # exit the loop if there are no more files to move
  done
done

答案 1 :(得分:0)

请考虑使用&&检查mv命令的结果并有条件地执行增量操作。

这是bash惯用语:

command && other-command-if-command-was successful

在上面的示例中,仅当命令返回零退出状态时,other-command才会执行。这是我对您的程序的修改:

x=0
while [[ $(ls -A Directory/jpg | wc -l) -gt 0 ]]
do
  for i in "${destination[@]}"
  do
    shuf -zn1 -e Directory/jpg/*.jpg | xargs -0 mv -vt $i/somedir 2>/dev/null && x=$((x + 1))
  done
done

上面的代码可能错误地假定xargs将返回mv的退出状态。我认为不会。相反,在这种情况下最好避免使用xargs。毕竟,shuf只返回一个条目。这是对代码的较大修改,效果更好:

x=0
while [[ $(ls -A Directory/jpg | wc -l) -gt 0 ]]
do
  for i in "${destination[@]}"
  do
    random_file=$(shuf -zn1 -e Directory/jpg/*.jpg) 
    mv "$random_file" "$i/somedir" && x=$((x + 1))
  done
done