cp 및 busybox와의 단방향 동기화

cp 및 busybox와의 단방향 동기화

cpBusyBox 1.35에 제공된 도구 및/또는 해당 도구가 없는 다른 도구를 사용하여 단방향으로 로컬 폴더를 동기화해야 합니다 rsync. 다음과 같은 결과를 얻고 싶었지만 cp -auv /source/ /target대상에서 제거된 항목은 삭제되지 않습니다. 대상은 궁극적으로 소스의 정확한 복사본이어야 하지만 이미 대부분을 갖고 있으므로 몇 가지 업데이트 재정의, 새로운 추가 및이동하다대화형 프롬프트 없이 필요할 수 있습니다.

고쳐 쓰다.cp -auv /source/ /target단방향 동기화에 필요한 모든 작업을 완료한 경우와는 별개로대상에서 이전 콘텐츠를 삭제합니다. 두 폴더를 "비교"하고 대상에 아직 존재하는 항목을 삭제하는 명령/스크립트가 있습니까? 아마도 비슷한 것이 diff -qr /source /target | xargs rm -rf효과가 있을까요?BusyBox 번호diff

답변1

나는 오래 전에 busybox 1.22에서 다음 스크립트를 성공적으로 사용했습니다. 시뮬레이션하기가 빠르고 더러워요아주 기본적인 rsync기능(시간 및 크기 기반 동기화 + 로깅 전용)물론 먼저 검토해야합니다그리고 파일 삭제를 처리하도록 기능을 향상시킬 수도 있습니다( rsync --del예: 기능).
또한 쉽게 제거할 수 있는 마지막 대화형 부분에 유의하세요. :

#!/bin/sh  

echo "#############################################"
echo "SHELL : $SHELL"
echo "BASH : $BASH"
echo "TERM : $TERM"
DATENOW=`date +%Y%m%d-%H%M%S` 
# last argument
LASTARG=`echo "$@" | awk ' { print $NF  }  '`
# penultimate argument
num_args=$# 
num_args_max=$num_args
let num_args=$num_args-1 
PENUARG=` echo "$@" | awk -v vk=$num_args ' { print $vk  }  ' `
TRG="$LASTARG"
echo "#############################################"

ProcedureStartCopyOneFile() {
  echo "*** COPY ***"
  echo "File not exists : $FILETRG" >> ~/.config/bashmv/bashmv.log
  echo -en "\r Copying ($i) (...)"
  echo "$i" | cpio -pvdmu "$TRG"
  echo -en "\r Copied ($i)."
  TRSS=` du -hs "$FILETRG" --apparent-size | cut -f 1 `
  SRSS=` du -hs "$i" --apparent-size | cut -f 1 ` 
  if  [ ! -d  "$i" ] &&  [ "$SRSS" != "$TRSS" ] ; then 
    echo "Different size: $FILETRG"
    echo "** WARNING **"
    echo "Different size: $FILETRG" >> ~/.config/bashmv/bashmv.log
    echo "** WARNING **" >> ~/.config/bashmv/bashmv.log
    exit
  else
    echo -en "\r Copied ($i) [OK]"
  fi
  echo "*** COPY OK ***"
  echo ".*.*"
}

ProcedureCopying() {

 echo "> Parameters: Source: $SRC  => Target: $TRG"


if [ -f "$SRC" ] || [  -d "$SRC" ] ; then 
  echo "Source: $SRC"
else
  echo "Directory or file source $SRC not found."
  exit
fi

if [ "$TRG" = "" ] ; then 
  exit
fi

if [ "$BASH" != "/bin/bash" ] ; then
  echo "Warning: You should use BASH : /bin/bash !"
  exit
else 
  echo "Intpreter BASH: $BASH [OK] "
fi

echo "** START ** "
[ ! -d ~/.config/bashmv ] && mkdir -p ~/.config/bashmv

[ ! -d  "$TRG" ] && mkdir -p "$TRG"
if [ "$LASTARG" = "--debug" ] ; then
  find "$SRC" -print
  exit
fi

find "$SRC" -print | grep -v "^$\|^#" | while read -r i ; do 
# echo "Processing $i"

FILETRG="${TRG}/${i}"
DATENOW=`date +%Y%m%d-%H%M%S` 
echo "> Start: .*.* ($i)"
if [ !  -f "$FILETRG" ] && [ ! -d  "$i"  ] ; then 
  echo ".*.*"
  echo "*** COPY ***"
  echo "File not exists : $FILETRG" >> ~/.config/bashmv/bashmv.log
  echo "$i" | cpio -pvdmu "$TRG"
  TRSS=` du -hs "$FILETRG" --apparent-size | cut -f 1 `
  SRSS=` du -hs "$i" --apparent-size | cut -f 1 ` 
  if  [ ! -d  "$i" ] &&  [ "$SRSS" != "$TRSS" ] ; then 
    echo "Different size: $FILETRG"
    echo "** WARNING **"
    echo "Different size: $FILETRG" >> ~/.config/bashmv/bashmv.log
    echo "** WARNING **" >> ~/.config/bashmv/bashmv.log
    exit
  else
    echo "Copied ($i) [OK]"
  fi
  echo "*** COPY OK ***"
  echo ".*.*"

elif [  -d "$i" ] ; then
  mkdir -p "$FILETRG"
  echo "Creating $FILETRG"

elif [ ! -d "$i" ] ; then
  TRSS=` du -hs "$FILETRG" --apparent-size | cut -f 1 `
  SRSS=` du -hs "$i" --apparent-size | cut -f 1 ` 
  # echo "Source: $SRSS vs $TRSS"

  if  [ -d  "$i" ] ; then
    echo "Directory."
  fi

  if  [ ! -d  "$i" ] ; then
    if [ -f "$FILETRG" ] && [ "$SRSS" = "$TRSS" ] ; then 
      echo "file $FILETRG exists. [Same size]"
    fi

    if   [ "$SRSS111kkk" = "$TRSS" ] ; then 
      echo "Different size: $FILETRG"
      echo "** WARNING **"
      echo "Different size: $FILETRG" >> ~/.config/bashmv/bashmv.log
      echo "** WARNING **" >> ~/.config/bashmv/bashmv.log
      FILETRGERROR="${TRG}/Error/${i}"
      [ ! -d  "$TRG/Error" ] && mkdir -p "$TRG/Error"
      echo "$TRSS" | cpio -pvdmu   "$TRG/Error/${DATENOW}-${i}"
    fi
  fi
fi

done

echo "Finished!"

if [ "$LASTARG" = "--rm" ] ; then 
  echo "Delete the directory: $SRC [y/n] ? "
  read inpud
  [ "$inpud" = "n" ] && exit
  rm -rf "$SRC"
fi

exit

익명의 도움이 되는 몇몇 저자에게 모든 공로를 인정합니다.

답변2

그 답을 찾기 위해서는 삭제, 검토, 비판이라는 마지막 단계가 필요하다. 먼저 대상을 업데이트합니다. 대상의 항목은 소스보다 최신일 수 없다고 가정합니다. 즉, 소스는 대상의 유일한 업데이트 에이전트입니다. 소스에서 제거된 이전 항목을 삭제해야 하지만 cp이렇게 하지 마세요. 아래와 같이 @ceving의 grep 명령을 사용하겠습니다.https://stackoverflow.com/a/51761017/612313

cp -auv /source/. /target
grep -v -F -x -f <(find /source -type f -printf '%P\n') <(find /target -type f -printf '%P\n')

그러면 /target/을 기준으로 /target의 모든 하위 폴더에 있는 모든 사용되지 않는 파일의 경로가 인쇄되지만 하위 폴더 자체는 인쇄되지 않습니다. 이제 이 출력을 공급하는 방법 rm /target/$1과 마지막 단계로 빈 하위 폴더를 찾아서 삭제하는 방법 만 배우면 됩니다 .

어쩌면 다음과 같을 수도 있습니다(줄이 너무 깁니다).

for i in $(grep -v -F -x -f <(find /source -type f -printf '%P\n') <(find /target -type f -printf '%P\n')); do echo /target/$i; done

또는,

grep -v -F -x -f <(find /source -type f -printf '%P\n') <(find /target -type f -printf '%P\n') | while read i; do echo /target/$i; done

전체 출력을 echo( rm)로 보낼 수 있지만 더 이상 모든 줄에 /target/을 추가할 수 없으므로 먼저 작업 폴더를 변경해야 하므로 더 짧습니다(?).

cd /target
echo $(grep -v -F -x -f <(find /source -type f -printf '%P\n') <(find . -type f -printf '%P\n'))

지금까지 내 최고의 후보 솔루션은 다음과 같습니다.

mkdir /target
pushd /target
cp -auv /source/. .
rm -v $(grep -v -F -x -f <(find /source -type f -printf '%P\n') <(find . -type f -printf '%P\n'))
find . -empty -type d -delete
popd

(어떤 이유로든 대상의 최신 파일은 건드리지 않습니다. 이 스크립트가 대상의 유일한 업데이트 프로그램인 경우에는 작동합니다.)

테스트할 질문 initrd: 우리는 어느 껍데기에 있는가? 애쉬 같은 것이라면 pushd/pod불가능할 수도 있고, $()확장팩도 불가능할 수도 있습니다. 내 결과를 보고할 예정입니다...

관련 정보