Linux - 仅复制新的和较大的文件

Linux - 仅复制新的和较大的文件

我有两个目录,其中有数千个文件,它们或多或少包含相同的文件。

我如何将所有不在 dirB 中的文件从 dirA 复制到 dirB,或者如果文件存在于 dirB 中,则仅当其较小时才覆盖它。

我知道有很多不同时间戳或不同文件大小的例子,但我只想在目标文件较小时覆盖,在任何情况下都不想在目标文件较大时覆盖。

我的问题背景:
我在 Minecraft 服务器上渲染了一个动态地图,但一些图块丢失或损坏。然后我在另一台具有更快 CPU 的机器上再次进行了渲染,并将所有新渲染的文件(~50GB / 6.000.000 ~4-10 KB PNG)复制到我的服务器上。之后我注意到我的新渲染中也有损坏的文件。

左:旧渲染,右:新渲染

旧 1 损坏 新 1

旧 2 新 2 损坏

因此,我不想覆盖所有文件,而只想覆盖较大的文件(损坏的文件携带的数据较少且较小)。

答案1

这可能是一种肮脏的方式,但我希望这是你想要的

#!/bin/bash

### Purpose:
# Copy huge amount of files from source to destination directory only if
# destination file is smaller in size than in source directory
###

src='./d1' # Source directory
dst='./d2' # Destination directory

icp() {
  f="${1}";
  [ -d "$f" ] && {
    [ ! -d "${dst}${f#$src}" ] && mkdir -p "${dst}${f#$src}";
    return
  }

  [ ! -f "${dst}/${f#$src/}" ] && { cp -a "${f}" "${dst}/${f#$src/}"; return; }
  fsizeSrc=$( stat -c %s "$f" )
  fsizeDst=$( stat -c %s "${dst}/${f#$src/}" )
  [ ${fsizeDst} -lt ${fsizeSrc} ] && cp -a "${f}" "${dst}/${f#$src/}"
}

export -f icp
export src
export dst

find ${src} -exec bash -c 'icp "$0"' {} \;

答案2

我遇到过类似的问题。我想将文件从远程文件夹同步到本地文件夹,但只复制大于相应本地文件的远程文件。

我使用 rsync 的解决方法是这样的,实际上是一个 bash 单行命令:

for x in $(ls -1 home/me/local/folder/*)
do
    eachsize=$(stat -c "%s")
    rsync -avz --progress --max-size=${eachsize} remote:/home/you/folder/${x} .
done

我想您可以明白这一点,因为两个文件夹之间的文件名是相同的,所以我遍历本地文件夹中的每个文件名并保留其大小,然后我将其作为限制,rsync 是否应该复制同名但大小不同的远程文件。

答案3

您可以使用同步命令

句法 :

-a = archive mode
-v = increase verbosity
-z = compress file data during the transfer
--progress = show progress during transfer

rsync -avz --progress <source path> <destination path>

您可以使用--delete从目标目录中删除多余的文件

rsync -avz --delete --progress <source path> <destination path>

因此你的命令将是:

rsync -avz --delete --progress dirA dirB

答案4

我已将其修改为如下形式:

# Copy src to destination if the src is larger.
function copy_if_larger() {
  local src="$1"
  local dest="$2"

  [ ! -f "$1" ] return
  [ ! -f "$2" ] return

  local srcSize=$( stat -c %s "$1")
  local dstSize=$( stat -c %s "$2")

  [ ${dstSize} -lt ${srcSize} ] && {
    cp -a "$1" "$2"
  }
  return
}

然后我编写了另一种方法来调整我想要复制的文件并将它们输入到 copy_if_larger 函数中。

function do_copy_if_larger() {
  # trim prefix
  local suffix=$(echo "$1" | cut -c 10-)
  copy_if_larger "$1" "/dest/path/$suffix"
}

# make the functions visible to the subshell.
export -f copy_if_larger
export -f do_copy_if_larger

# copy all larger jpeg files over /dest/path
find . -name '*jpg' | xargs -n 1 bash -c 'do_copy_if_larger "$@"' {}

相关内容