정규식을 사용하여 rsync를 사용하면 일부 파일 만 포함


11

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]*'및 다른 조합을 사용해 보았지만 여전히 가지 않습니다.

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


4
왜 사용하고 --exclude='*'있습니까?

2
포함의 일부가 아닌 모든 것을 제외합니다.

'패턴으로 인해 1Name.txt 파일을 숨기는 것은 다음을 나타냅니다 :- "--exclude 규칙이 명령에 있어야합니까?" 또는 일부 파일을 제외하려면 왜 " "입니다.
Akshay Patil

답변:


5

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/

그것을 실행하려고 시도했지만 cut 명령에 문제가 발생했습니다. 그것이 -t유효한 스위치 인 것 같습니다 .

편집 : 나는 -t는 유효한 스위치가 아님을 의미했습니다

죄송합니다. -d 여야합니다. 나는 sed를 사용하여 시작한 다음 더 명확하다고 생각했기 때문에 잘라 내기로 변경했지만 내 명령을 편집하는 것을 잊었습니다 .S

후속 조치 : 파일 이름 + 확장명 조합과 일치 할 때 scrip을 편집하여 인수를 취하려고했습니다 (예 : $ 1 = path_to_search, egrep 패턴으로 $ 2). 그 부분은 제대로 작동하지만 예상 목록이 있지만 rsync는 복사하지 못합니다. 예제에서와 같이 단일 이름 문자 디렉토리에서만 작동하는 것 같습니다 (a) 부모 / 또는 소스 디렉토리를 기반으로 문자를 자르려면 cut 명령을 수정해야한다고 생각합니다. 킨다는 그 방법을 잃었다 :
user1957413

아 맞아요 모든 길이의 디렉토리 이름에서 작동해야하지만 접두사 부분에 다른 수의 슬래시가 있기 때문에 현재 디렉토리 외부 의 디렉토리를 참조하자마자 실패 합니다. 이를 수정하려면 아마도 cut 대신 sed를 사용하는 것이 가장 쉽습니다. sed "s#^$1/*##" buuuut는 #을 포함하는 경로에서 중단됩니다. 이 문제를 해결하려면 들어오는 디렉토리 이름을 인용해야합니다. prefix=$(echo "$1" | sed 's#/#\\/#g')그리고 sed "s/^$prefix\\/*//" bash 인용의 하위 요소는 약간 악몽입니다.)
sqweek

7

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

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

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


단. 이것도 효과가있었습니다. b 안에 a 폴더를 가져 왔는데 a / b /를 소스 및 대상으로 사용하여 수정되었습니다. 감사!
user1957413

-f '+ * [Nn] [Aa] [Mm] [E] **'(끝에 별 2 개)를 사용하여 특정 이름을 가진 모든 디렉토리의 내용을 포함하십시오.
공포증

2

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/

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


1

위의 @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/

감사. 정규식을 줄 끝에 고정시키는 것과 동등한 수정으로 내 대답을 편집했습니다 ( sub("/[^/]*$")).
sqweek

0

가장 경험이 많은 언어이기 때문에 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 *

0

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

허용 된 답변보다 더 간단합니다. 부모 디렉토리를 자동으로 포함하는 --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합니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.