내 서버의 중앙 저장소에 연구용 파일 모음을 구축했습니다. 나는 지속적으로 저장소를 관리하고 디렉토리의 이름을 바꾸고 이동하여 디렉토리의 트리 구조를 변경합니다. 나는 저장소에 있는 파일의 로컬 복사본을 지속적으로 업데이트하고 편집하고 있습니다. 이로 인해 저장소에 클라이언트의 새 파일로 대체해야 하는 파일이 있지만 디렉터리 트리가 변경되는 상황이 발생합니다.
rsync
아직 배우지 않은 옵션이 있나요 ?디렉터리 트리 변경 시 rsync가 작동하지 않는 것으로 나타났습니다. 나는 테스트했다rsync --existing
아니면 좀 있나요?명령줄 -fu사용 find
하고 mv
?웹 등을 검색해 보세요.자원찾기만 찾아서 바꾸기파일에예.
-- 업데이트 1 가능하다면 @meuh 및 @Lqueryvg에게 훌륭한 답변을 제공하겠습니다. @css1971이 그의 답변에 추가되어 파일 관리를 전복시키는 강력한 사례를 만든 것을 확인했습니다. 안타깝게도 시간이 부족하여 보상 시스템이 제가 가장 좋아하는 답변을 선택했습니다. 나는 모든 답변이 매우 유익하다는 것을 알았습니다. 모두에게 감사드리고 싶습니다. 다음 주말에 더 사려 깊은 의견을 제시할 수 있기를 기대합니다.
답변1
[내 댓글에서 OP로 확장]. flat
모든 파일의 복사본을 포함하지만 단순 목록에 있는 저장소에 디렉터리를 만듭니다 . 복사본은 하드 링크이므로 공간을 차지하지 마십시오. 로컬 컴퓨터에서도 동일한 작업을 수행하세요. 그런 다음 로컬 플랫 디렉터리에서 원격 플랫 디렉터리로 rsync할 수 있습니다. rsync를 사용하면 원격 하드 링크가 보존되므로 모든 원격 파일이 업데이트됩니다 --inplace
. 플랫 디렉터리는 rsync 이전에 스크립트로 생성되고 rsync 이후 삭제될 수 있습니다.
다음은 실행 가능한 개념 증명 테스트 스크립트입니다.
#!/bin/bash
dosync(){ # function to create flat trees and rsync them
mkdir flat
mkdir flatl
find repo -type f -exec ln {} flat \;
find local -type f -exec ln {} flatl \;
rsync -aHv --inplace flatl/ flat
rm -fr flat flatl
}
# create repo and local dirs with same content. 3 empty files
cd /tmp || exit
mkdir repo
( cd repo; touch a b c )
mkdir local
rsync -a repo/ local
dosync
echo hi >local/a # example change of local file a
dosync
mkdir repo/new # example move of repo file b
mv repo/b repo/new/
echo hello >local/b # change local file b
dosync
ls -lR repo local
# rm -fr flat flatl repo local
반대 방향의 경우, dosync가 로컬 수정 사항을 저장소로 전송한 후 간단히 rm -fr local
"rsync -a repo/local"을 사용하여 전체 저장소를 로컬 파일 시스템에 복사할 수 있습니다. 대신 비슷한 기술을 사용하여 저장소로 전송해야 하는 새 파일 수를 줄일 수 있습니다.
reversesync(){
mkdir flat
mkdir flatl
find repo -type f -exec ln {} flat \;
find local -type f -exec ln {} flatl \;
mv flat repo/flat
mv flatl local/flat # not flatl!
rsync -aHv --delete repo/ local
rm -fr repo/flat local/flat
}
그러면 rsync가 하드 링크된 파일을 보고 복사를 피할 수 있도록 평면화된 트리가 각각 저장소와 로컬 디렉터리로 이동됩니다. (분명히 이번에는 플랫 디렉토리의 이름이 동일해야 합니다).
변경된 알려진 파일만 있는 경우 find
저장소에서 이를 사용하여 트리에서 새 위치를 가져오고 거기에서 파일을 동기화할 수 있습니다. 예를 들어:
file=mychangedfile.abc
to=$(find repo -name "$file")
from=$(find local -name "$file")
rsync -av "$from" "$to"
이는 저장소가 설치되어 있다고 가정합니다 ssh repo find...
. 그렇지 않으면 저장소에 ssh를 사용할 수 없는 경우 rsync를 사용하여 가상 로컬 대상에 파일 목록을 가져오고 원하는 파일을 추출할 수 있습니다.
to=$(rsync -a --list-only repo dummy | awk '/\/'"$file"'$/{print $NF}')
답변2
나는 rsync가 find와 mv와 마찬가지로 잘못된 도구라고 생각합니다. 내 제안은 소프트웨어 구성 관리 시스템을 사용하는 것입니다. 여기에는 Subversion, Git, Mercurial, Bazaar 등이 포함됩니다. 이들 모두는 트리 구조 변경을 쉽게 처리할 수 있습니다.
설명하는 구조에는 클라이언트 시스템에 트리 구조 A가 있고 보조 위치(로컬 또는 원격일 수 있음)에 저장소 트리 구조 B가 있습니다.
두 가지를 모두 업데이트한 경우 이제 경쟁 변경 사항을 적용해야 합니다.올바른 순서로두 저장소를 일관되게 유지하십시오. 순서대로 적용되지 않으면 구조가 더 이상 존재하지 않기 때문에 한 구조에 대한 변경 사항을 다른 구조에 직접 적용할 수 없는 상황이 발생하게 됩니다.
현재로서는 두 저장소를 일관되게 만들기 위해 어떤 변경 사항을 적용해야 하는지 자동으로 알 수 있는 rsync 옵션이 없습니다. 그것은 그것을 위해 설계된 것이 아닙니다. 한 저장소가 다른 저장소와 똑같이 보이도록 만들 수는 있지만 한 번에 한 쪽만 변경하면 됩니다. 예를 들어 A, B, A를 교대로 변경합니다. 언제든지 패브릭 A 또는 B 중 하나를 마스터로 지정하고 변경 사항을 동기화해야 합니다.한 방향으로만한 번.
나는 또한 당신이 찾고 있는 결과를 달성하는 간단한 commandline-fu 명령이 있다고 믿지 않으므로 이제 당신은 쉘 프로그래밍 영역에 있습니다.
너만 변했다면트리 구조B 그리고 오직문서 내용A가 변경된 파일의 파일 이름을 찾고 B에서 해당 파일의 새 경로를 얻은 다음 일치하도록 A의 트리 구조를 수정하는 것은 비교적 간단한 작업입니다. 이것오직파일 이름이 고유한 경우 유효합니다.
A의 구조를 B와 일치시키는 의사코드는 다음과 같습니다.
generate list of file names in A and their paths
For each of the names in A
find that same name in B
If the path of A is the same as B
continue to the next file
if not then
create the directory structure in A
move the file to the new location.
if the old path in A is now empty
delete the directory.
repeat
check if the parent directory is now empty, then delete it.
until a non empty directory
트리 구조가 동기화되면 A는 B의 정확히 동일한 경로로 직접 복사될 수 있습니다. rsync의 --update 옵션을 사용하면 이전 파일을 새 파일로 양방향으로 덮어쓸 수 있습니다.
파일 이름 선택기로 find를 사용하여 로컬로 변경된 파일을 기존 저장소에 복사하는 일부 샘플 셸 코드입니다.
#!/bin/bash
set -xv
localRepo=/tmp/a
remoteRepo=/tmp/b
rm -rf $localRepo $remoteRepo
mkdir -p $localRepo/1/2/ $localRepo/1/3/
mkdir -p $remoteRepo/2/1/ $remoteRepo/3/1/
echo a12 > $localRepo/1/2/file
echo b21 > $remoteRepo/2/1/file
echo a13 > $localRepo/1/3/file1
echo b31 > $remoteRepo/3/1/file1
echo ex1
cat $localRepo/1/2/file $remoteRepo/2/1/file
echo ex2
cat $localRepo/1/3/file1 $remoteRepo/3/1/file1
localFileNameList=$(find $localRepo -type f -mtime -1 | xargs -L 1 basename)
for localFileName in $localFileNameList
do
localFilePath=$(find $localRepo -name $localFileName | xargs dirname)
backFile=$(find $remoteRepo -name $localFileName)
repoDir=$(dirname $backFile)
cp $localFilePath/$localFileName $repoDir
done
echo ex1
cat $localRepo/1/2/file $remoteRepo/2/1/file
echo ex2
cat $localRepo/1/3/file1 $remoteRepo/3/1/file1
예를 들어, 사용하기 쉬운 SCM 중 하나인 Subversion으로 파일 시스템을 가져오려면 다음을 수행합니다.
e.g.
mkdir /tmp/svn
svnadmin create /tmp/svn/reponame
cd /tmp/b
svn import -m "The initial import " file:///tmp/svn/reponame
Adding 2
Adding 2/1
Adding 2/1/file
Adding 3
Adding 3/1
Adding 3/1/file1
그런 다음 저장소를 확인하고 로컬을 변경합니다.
$ cd /tmp
$ svn checkout file:///tmp/svn/reponame
A reponame/2
A reponame/2/1
A reponame/2/1/file
A reponame/3
A reponame/3/1
A reponame/3/1/file1
Checked out revision 1.
/tmp:
$ cd reponame/
/tmp/reponame:
$ ls -ltr
total 8
drwxrwxr-x 3 css1971 css1971 4096 Apr 11 12:04 3
drwxrwxr-x 3 css1971 css1971 4096 Apr 11 12:04 2
/tmp/reponame:
$ svn move 3 4
A 4
D 3
D 3/1
D 3/1/file1
/tmp/reponame:
변경 사항을 저장소에 다시 커밋합니다.
$ svn commit -m "renamed dir"
Deleting 3
Adding 4
Committed revision 2.
이 시점부터 svn 도구를 사용하여 일반적인 작업 흐름의 일부로 저장소를 작동합니다.
유용한 명령:
svn import
svn update
svn commit
svn del
svn cp
svn mv
답변3
직업인 것 같아요조화! 나는 몇 년 동안 그것을 플레이하지 않았지만 당신이 요구하는 것과 정확히 일치할 것이라고 생각합니다... 홈 페이지에는 다음과 같이 적혀 있습니다.
Unison은 OSX, Unix 및 Windows용 파일 동기화 도구입니다. 이를 통해 파일 및 디렉터리 모음의 두 복사본을 다른 호스트(또는 동일한 호스트의 다른 디스크)에 저장하고 별도로 수정한 다음 각 복사본의 변경 사항을 다른 복사본에 전파하여 업데이트할 수 있습니다.
살펴보고 계속해서 소식을 전해 주세요! ;)
답변4
당신은 절대적으로할 수 있는디렉터리 구조 변경 작업을 수행하며 rsync
여러분이 알지 못할 수도 있는 몇 가지 흥미로운 옵션, 특히 -H
하드 링크를 보존하는 옵션이 있습니다.
내 자신의 시나리오를 설명하겠습니다. 이것이 당신에게 효과가 있을 수도 있고 없을 수도 있지만, 적어도 당신이 그것을 찾길 바랍니다.흥미로운.
상상하다:
rsync
다른 디렉터리(예: 원격 시스템 또는 외부 디스크)에 복사되는 디렉터리 트리에 많은 파일이 포함된 큰 디렉터리가 있습니다 .
디렉터리를 재구성하고 파일 이름을 바꾸거나 파일을 다른 하위 디렉터리로 이동하고 싶지만 파일 자체의 내용은 변경하지 않으려고 합니다.
그러나 다음에 실행될 때 rsync
이동되었거나 이름이 변경된 모든 파일에 대한 데이터가 다시 복사됩니다. 해당 파일이 이미 대상에 존재하더라도(다른 위치에 있음에도 불구하고). 데이터를 다시 복사하지 않고 파일 위치를 동기화하는 방법은 다음과 같습니다.빠른.
분명히 테스트 시스템에서 먼저 시도해 본 다음조심하세요당신의 데이터로.
소스 데이터가 에 있고 /tmp/src/dir/
대상 복제본이 에 있다고 가정합니다 /tmp/dst/
. 이는 원격 rsync
대상에서도 작동합니다.
0.
설정 예:
$ mkdir -p /tmp/src/dir; cd $_
$ fallocate -l 1000 a
$ fallocate -l 1000 b
$ fallocate -l 1000 c
$ tree /tmp/src
/tmp/src
`-- dir
|-- a
|-- b
`-- c
1.
초기 사본:
$ mkdir /tmp/dst; rsync -havHP /tmp/src/dir /tmp/dst
이 시점에서 /tmp/src/dir/
그 안에 있는 모든 파일과 디렉터리가 /tmp/dst/
.
$ tree /tmp/dst
/tmp/dst
`-- dir
|-- a
|-- b
`-- c
2.
소스에 있는 디렉터리 구조의 하드 링크된 복사본을 만듭니다. 참고: 이는 파일과 디렉터리가 많은 경우에도 마찬가지입니다.곧, 메타데이터만 복사하기 때문입니다.
$ cd /tmp/src/; mv dir dir.old
$ cp -rlp dir.old dir
# -l = link not copy
# -p = preserve permissions etc
삼.
/tmp/src/dir
파일 이동 및 이름 바꾸기를 포함하여 에서 많은 변경을 수행합니다 . 이 예에서는 모든 파일을 새 하위 디렉터리로 이동하겠습니다.
$ cd /tmp/src/dir; mkdir sub
$ mv a b c sub
$ tree /tmp/src/dir
/tmp/src/dir
`-- sub
|-- a
|-- b
`-- c
4.
이전 디렉토리 구조와 새 디렉토리 구조를 바꾼 후 rsync
대상 옆에빠른, 대상의 하드 링크만 복사하기 때문에 파일 내용이 변경되지 않는 한 데이터는 복사되지 않습니다.
$ cd /tmp/src
$ mv dir dir.new; mv dir.old dir
$ rsync -havHP --delete-after --no-inc-recursive \
/tmp/src/dir /tmp/src/dir.new /tmp/dst
rsync의 출력은 파일 내용을 다시 전송하지 않는다는 것을 보여줍니다.
building file list ...
9 files to consider
dir.new/
dir.new/sub/
dir.new/sub/a => dir/a
dir.new/sub/b => dir/b
dir.new/sub/c => dir/c
sent 165 bytes received 45 bytes 420.00 bytes/sec
total size is 6.00K speedup is 28.57
5.
마지막으로 소스와 대상 모두에서 원본 콘텐츠를 새 콘텐츠로 바꿔서 dir
정리합니다 .dir.new
$ cd /tmp/src
$ rm -rf dir
$ mv dir.new dir
$ cd /tmp/dst
$ rm -rf dir
$ mv dir.new dir
위의 해결 방법은 다소 번거롭고 디렉터리 교환 중에 다른 사람이 데이터에 액세스하는 것에 대해 주의해야 하지만 rsync
어떤 경우에는 많은 시간을 절약할 수 있는 흥미로운 기능임은 분명합니다.