"find -exec mv"는 이전에 이동된 동일한 파일을 이동하려고 시도합니다.

"find -exec mv"는 이전에 이동된 동일한 파일을 이동하려고 시도합니다.

내 잘못된 명령:

find . -type f -name '*2019*' -exec mv {} ./backup_2019 \;

결과:

mv: ‘./backup_2019/2019-A.txt’ and ‘backup_2019/2019-A.txt’ are the same file
mv: ‘./backup_2019/2019-B.txt’ and ‘backup_2019/2019-B.txt’ are the same file
mv: ‘./backup_2019/2019-C.txt’ and ‘backup_2019/2019-C.txt’ are the same file

이전에 이동했던 파일을 찾은 것 같아요. MaxDeepth를 사용하지 않고 이 문제를 해결할 수 있나요? 대상 디렉터리만 제외하는 방법이 있나요?

답변1

제외할 대상 디렉터리를 무시해야 합니다.

find . -path './backup_2019' -prune -o -type f -name '*2019*' -exec mv {} ./backup_2019 \;

연산자 사이의 암시적 AND는 -oOR( )보다 더 밀접하게 연결되어 있으므로 다음과 같이 변환됩니다.(경로가 일치하는 경우 건너뛰기 ./backup_2019) 또는 ( mv일치하는 파일이 있는 경우 *2019*).

답변2

find백업 디렉터리 에 들어가지 않으려면 해당 디렉터리를 무시해야 합니다 . 이미 가지고 있다답변이를 수행하는 방법을 보여주십시오.

그러나 이 방법으로 파일을 백업하면 데이터가 삭제될 위험이 있습니다. 서로 다른 하위 디렉터리에 있는 두 개 이상의 파일이 동일한 이름을 갖는 경우 대상 백업 디렉터리에서 서로 덮어쓰게 됩니다.

데이터를 백업하려면 실제 백업 소프트웨어(예: restic. 이것이 가능하지 않은 경우 백업할 파일의 상대 경로를 유지하는 솔루션을 사용하십시오.

다음 명령은 이름에 하위 문자열이 포함된 모든 파일을 디렉터리로 rsync복사(이동 아님)합니다 .2019backup_2019

rsync --itemize-changes --archive --prune-empty-dirs \
    --exclude='/backup_2019/***' --include='*/' --include='*2019*' --exclude='*' \
    ./ ./backup_2019

./backup_2019이렇게 하면 전송할 파일이나 디렉터리를 내부적으로 찾지 않고 하위 문자열이 포함된 모든 항목을 복사합니다 2019. 결국 대상의 빈 디렉터리는 삭제됩니다. 복사된 모든 내용은 backup_2019현재 디렉터리의 파일과 동일한 위치 에 복사됩니다 .

예:

$ tree -F
.
|-- dir1/
|   |-- file-1
|   |-- file-2019-A
|   `-- subdir/
|       |-- file-2
|       `-- file-2019-B
|-- dir2/
|   |-- file-1
|   |-- file-2019-A
|   `-- subdir/
|       |-- file-2
|       `-- file-2019-B
`-- dir3/
    |-- file-1
    |-- file-2019-A
    `-- subdir/
        |-- file-2
        `-- file-2019-B
$ rsync --itemize-changes --archive \
    --prune-empty-dirs \
    --exclude='/backup_2019/***' --include='*/' --include='*2019*' --exclude='*' \
    ./ ./backup_2019
cd+++++++++ ./
cd+++++++++ dir1/
>f+++++++++ dir1/file-2019-A
cd+++++++++ dir1/subdir/
>f+++++++++ dir1/subdir/file-2019-B
cd+++++++++ dir2/
>f+++++++++ dir2/file-2019-A
cd+++++++++ dir2/subdir/
>f+++++++++ dir2/subdir/file-2019-B
cd+++++++++ dir3/
>f+++++++++ dir3/file-2019-A
cd+++++++++ dir3/subdir/
>f+++++++++ dir3/subdir/file-2019-B
$ tree -F
.
|-- backup_2019/
|   |-- dir1/
|   |   |-- file-2019-A
|   |   `-- subdir/
|   |       `-- file-2019-B
|   |-- dir2/
|   |   |-- file-2019-A
|   |   `-- subdir/
|   |       `-- file-2019-B
|   `-- dir3/
|       |-- file-2019-A
|       `-- subdir/
|           `-- file-2019-B
|-- dir1/
|   |-- file-1
|   |-- file-2019-A
|   `-- subdir/
|       |-- file-2
|       `-- file-2019-B
|-- dir2/
|   |-- file-1
|   |-- file-2019-A
|   `-- subdir/
|       |-- file-2
|       `-- file-2019-B
`-- dir3/
    |-- file-1
    |-- file-2019-A
    `-- subdir/
        |-- file-2
        `-- file-2019-B

13 directories, 18 files

백업된 파일의 "복사" 대신 "이동"을 수행하는 --remove-source-files옵션을 목록에 추가할 수 있습니다 .rsync

답변3

아직 해결책을 찾지 못했다면 maxlength 옵션을 사용해 보세요. 또는 현재 검색된 하위 폴더가 아닌 다른 폴더에 백업해 보세요.

전에 발견했습니다. -최대 깊이 1 -name"2019" -exec mv '{}' ./backup_2019 ;

답변4

글쎄, 이것은 예상치 못한 나쁜 놀라움이었습니다. 어쨌든 잊어버리고 -exec다른 것을 시도해 볼 수 있습니다.

find . -type f -name '*2019*' -print0 | while read -d $'\0' fpath; do mv "$fpath" ./backup_2019; done

여기서는 스크립트가 공백이 포함된 파일 이름을 지원하도록 공백(기본값)을 구분 기호로 null 문자로 추가 -print0하고 바꿉니다.-d $'\0'

파이프를 사용하면 하위 쉘이 생성되고 "전역" 스크립트 변수에 대한 액세스가 손실됩니다.

루프 내에서 "전역 변수"에 액세스해야 하는 경우 파이프 대신 프로세스 대체를 사용할 수 있습니다.

myvar=""
while read -d $'\0' fpath 
do 
  mv "$fpath" ./backup_2019
  myvar="Hello World" 
done < <(find . -type f -name '*2019*' -print0)

관련 정보