정규식을 사용하여 rsync를 사용하면 일부 파일 만 포함 pattern * [sender]

rsync를 실행하여 파일 이름 패턴을 기반으로 경로에 재귀 적으로 일부 파일을 복사하려고합니다 (대소 문자 구분 안함) . 이것이 rsync를 실행하기 위해 수행 한 작업입니다.

$ rsync -avvz --include ='*/' --include='.*[Nn][Aa][Mm][E].*' --exclude='*' ./a/ ./b/

아무것도 복사되지 않으면 디버그 출력에 다음이 표시됩니다.

[sender] hiding file 1Name.txt because of pattern *
[sender] hiding file 1.txt because of pattern *
[sender] hiding file 2.txt because of pattern *
[sender] hiding file Name1.txt because of pattern *
[sender] hiding directory test1 because of pattern *
[sender] hiding file NaMe.txt because of pattern *

나는 : --include='*[Nn][Aa][Mm][E]*'및 다른 조합을 사용해 보았지만 여전히 가지 않습니다.

정규식을 사용하여 파일을 포함시키는 방법에 대한 아이디어가 있습니까?



답변

rsync는 정규식을 사용하지 않습니다. 조금 이상해 보이지만 찾기와 grep을 할 수 있습니다. 대상 파일을 찾으려면

find a/ |
grep -i 'name'

그러나 모두 “a /”라는 접두어가 붙습니다. 이것은 말이 되겠지만, rsync에 허용되는 포함 패턴 목록이며 “a /”접두사가 rsync에 대해 작동하지 않기 때문에 ” 잘라내어 제거합니다.

find . |
grep -i 'name' |
cut -d / -f 2-

rsync는 제외 목록에서 디렉토리를 검색하지 않기 때문에 여전히 문제가 있습니다. 하위 디렉토리의 파일은 여전히 ​​누락됩니다. awk를 사용하여 일치하는 파일의 하위 디렉토리를 포함 패턴 목록에 추가합니다.

find a/ |
grep -i 'name' |
cut -d / -f 2- |
awk -F/ '{print; while(/\//) {sub("/[^/]*$", ""); print}}'

남은 것은리스트를 rsync로 보내는 것입니다. –include-from =-인수를 사용하여 표준 입력에서 rsync 할 패턴리스트를 제공 할 수 있습니다. 따라서 모두 :

find a/ |
grep -i 'name' |
cut -d / -f 2- |
awk -F/ '{print; while(/\//) {sub("/[^/]*$", ""); print}}' |
rsync -avvz --include-from=- --exclude='*' ./a/ ./b/

소스 디렉토리 ‘a’는 “a /”와 “./a/”의 두 가지 경로를 통해 참조됩니다. 이것은 미묘하지만 중요합니다. 보다 일관성있는 작업을 수행하기 위해 마지막으로 한 가지 변경을하고 항상 소스 디렉토리를 “./a/”로 참조합니다. 그러나 이것은 find 명령의 결과 앞에 추가 “./”가 있으므로 cut 명령이 변경되어야 함을 의미합니다.

find ./a/ |
grep -i 'name' |
cut -d / -f 3- |
awk -F/ '{print; while(/\//) {sub("/[^/]*$", ""); print}}' |
rsync -avvz --include-from=- --exclude='*' ./a/ ./b/


답변

rsync의 필터 옵션을 사용하는 것이 좋습니다. 예를 들어 다음을 입력하십시오.

rsync -vam -f'+ *[Nn][Aa][Mm][E]*' -f'+ */' -f'- *' a b

첫 번째 필터 규칙은 rsync에 포함 할 패턴을 알려줍니다. 두 번째 규칙은 rsync에게 순회의 모든 디렉토리를 검사하도록 지시하는 데 필요합니다. 빈 디렉토리가 포함되지 않도록 -m옵션 으로 명시 적으로 제외됩니다 . 마지막 필터 규칙은 rsync에 아직까지 일치하지 않은 나머지 패턴을 모두 처리하도록 지시합니다.


답변

ZSH를 사용하는 경우 (#i) 플래그를 사용하여 대소 문자 구분을 해제 할 수 있습니다. 예:

$ touch NAME
$ ls (#i)*name*
NAME

ZSH는 일반 경로와 동일하게 지정되지만 초기 ~

$ touch aa ab ac
$ ls *~*c
aa ab

제외를 연결할 수 있습니다.

$ ls *~*c~*b
aa

마지막으로 어떤 종류의 파일 (디렉토리, 파일 등)을 반환할지 지정할 수 있습니다. 이것은 디렉토리의 경우 (/) 및 파일의 경우 (.)로 수행됩니다.

$ touch file
$ mkdir dir
$ ls *(.)
file

이 모든 것을 기반으로 다음과 같이 명령을 수행합니다.

rsync -avvz *(/) (#i)*name* ./a/ ./b/

(이 선택기에서 제외 할 필요가 없습니다)


답변

위의 @sqweek의 답변은 훌륭하지만 awk부모 디렉토리를 생성하는 스크립트에 버그가 있다고 생각 합니다.

$ echo a/b/c/d | awk -F/ '{print; while(/\//) {sub("/[^/]*", ""); print}}'
a/b/c/d
a/c/d
a/d
a

gensub대신 대신 사용하여 문제를 해결할 수있었습니다 .

$ echo a/b/c/d | awk -F/ '{print; while(/\//) { $0=gensub("(.*)/[^/]*", "\\1", "g"); print}}'
a/b/c/d
a/b/c
a/b
a

따라서 awk비트가 변경된 그의 전체 솔루션은 다음과 같습니다.

find ./a/ |
grep -i 'name' |
cut -d / -f 3- |
awk -F/ '{print; while(/\//) { $0=gensub("(.*)/[^/]*", "\\1", "g"); print}}' |
rsync -avvz --include-from=- --exclude='*' ./a/ ./b/


답변

가장 경험이 많은 언어이기 때문에 C # 스크립트로 시도했습니다. 포함하고 싶은 파일 목록을 만들 수는 있지만 rsync는 여전히 하이킹 중이라고 말합니다. 폴더를 작성하지만 파일을 무시합니다. 여기 내가 가진 것이 있습니다 ..

먼저 디렉토리의 내용 :

~/mono$ ls -l
total 24
drwxr-xr-x 5 me me 4096 Jan 15 00:36 a
drwxr-xr-x 2 me me 4096 Jan 15 00:36 b
drwxr-xr-x 3 me me 4096 Jan 14 00:31 bin
-rw-r--r-- 1 me me 3566 Jan 15 00:31 test.cs
-rwxr-xr-x 1 me me 4096 Jan 15 00:31 test.exe
-rwxr--r-- 1 me me  114 Jan 14 22:40 test.sh

그런 다음 C # 스크립트의 출력 :

~/mono$ mono test.exe

/a/myfile/myfileseries.pdf
/a/myfile2/testfile.pdf

그리고 디버그 출력 :

~/mono$ mono test.exe | rsync -avvvz --include='*/' --include-from=- --exclude='*' ./a/ ./b/
[client] add_rule(+ */)
[client] parse_filter_file(-,20,3)
[client] add_rule(+ /a/myfile/myfileseries.pdf)
[client] add_rule(+ /a/myfile2/testfile.pdf)
[client] add_rule(- *)
sending incremental file list
[sender] make_file(.,*,0)
[sender] hiding file 1Name.txt because of pattern *
[sender] showing directory myfile2 because of pattern */
[sender] make_file(myfile2,*,2)
[sender] hiding file 1.txt because of pattern *
[sender] hiding file 2.txt because of pattern *
[sender] hiding file Name1.txt because of pattern *
[sender] showing directory test1 because of pattern */
[sender] make_file(test1,*,2)
[sender] hiding file NaMe.txt because of pattern *
[sender] showing directory myfile because of pattern */
[sender] make_file(myfile,*,2)
send_file_list done
send_files starting
[sender] hiding file myfile/myfileseries.pdf because of pattern *
[sender] hiding file myfile2/testfile.pdf because of pattern *
[sender] hiding file test1/test.txt because of pattern *


답변

[편집] 로컬에서만 작동합니다. 원격 경로의 경우 디렉토리 구조를 먼저 작성해야합니다.

허용 된 답변보다 더 간단합니다. 부모 디렉토리를 자동으로 포함하는 –file-from을 사용하고 % P를 사용하여 파일 경로를 printf

find /tmp/source -wholename '*[Nn][Aa][Mm][E]*' -printf '%P\n' | rsync -vzrm --exclude='*/' --files-from=- /tmp/source/ /tmp/target/

따라서 당신은 findand 만 사용해야 rsync합니다.


답변