내 잘못된 명령:
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는 -o
OR( )보다 더 밀접하게 연결되어 있으므로 다음과 같이 변환됩니다.(경로가 일치하는 경우 건너뛰기 ./backup_2019
) 또는 ( mv
일치하는 파일이 있는 경우 *2019*
).
답변2
find
백업 디렉터리 에 들어가지 않으려면 해당 디렉터리를 무시해야 합니다 . 이미 가지고 있다답변이를 수행하는 방법을 보여주십시오.
그러나 이 방법으로 파일을 백업하면 데이터가 삭제될 위험이 있습니다. 서로 다른 하위 디렉터리에 있는 두 개 이상의 파일이 동일한 이름을 갖는 경우 대상 백업 디렉터리에서 서로 덮어쓰게 됩니다.
데이터를 백업하려면 실제 백업 소프트웨어(예: restic
. 이것이 가능하지 않은 경우 백업할 파일의 상대 경로를 유지하는 솔루션을 사용하십시오.
다음 명령은 이름에 하위 문자열이 포함된 모든 파일을 디렉터리로 rsync
복사(이동 아님)합니다 .2019
backup_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)