Bash의 확장 와일드카드를 사용하여 점으로 시작하는 파일 이름을 무효화하세요.

Bash의 확장 와일드카드를 사용하여 점으로 시작하는 파일 이름을 무효화하세요.

다음 파일이 있다고 가정해 보겠습니다.

xb@dnxb:/tmp/aaa/webview$ tree -F -C -a .
.
├── .git/
├── ss/
├── y
└── !yes/

3 directories, 1 file
xb@dnxb:/tmp/aaa/webview$ 

다음 이스케이프를 사용하면 부정이 제대로 작동합니다 !yes.!\

xb@dnxb:/tmp/aaa/webview$ mkdir /tmp/aaa/webview2; cp -r -a !(\!yes) /tmp/aaa/webview2                                         
xb@dnxb:/tmp/aaa/webview$ l /tmp/aaa/webview2
total 16K
39331773 -rw-rw-r-- 1 xiaobai xiaobai ?    0 Jul  27 05:07 y
39331771 drwxrwxr-x 2 xiaobai xiaobai ? 4.0K Jul  27 05:43 .git/
39331772 drwxrwxr-x 2 xiaobai xiaobai ? 4.0K Jul  27 05:43 ss/
39331757 drwxrwxr-x 4 xiaobai xiaobai ? 4.0K Jul  27 05:44 ../
39331770 drwxrwxr-x 4 xiaobai xiaobai ? 4.0K Jul  27 05:44 ./
xb@dnxb:/tmp/aaa/webview$

하지만 !(.git)작동하지 않습니다 :

xb@dnxb:/tmp/test/hello$ rm -r /tmp/test; shopt -s extglob; shopt -s dotglob; mkdir -p /tmp/test/hello; mkdir /tmp/test/hello2; cd /tmp/test/hello; mkdir '.git'; cp -r -a !(.git) /tmp/test/hello2/; ls -la /tmp/test/hello2/
cp: will not create hard link '/tmp/test/hello2/hello' to directory '/tmp/test/hello2/.'
cp: cannot copy a directory, '..', into itself, '/tmp/test/hello2/'
total 16
drwxrwxr-x 4 xiaobai xiaobai 4096 Jul  27 16:05 .
drwxrwxr-x 4 xiaobai xiaobai 4096 Jul  27 16:05 ..
drwxrwxr-x 2 xiaobai xiaobai 4096 Jul  27 16:05 .git
drwxrwxr-x 2 xiaobai xiaobai 4096 Jul  27 16:05 hello2
xb@dnxb:/tmp/test/hello$ 

.일하지 않을 때 탈출 \:

xb@dnxb:/tmp/aaa/webview$ rm -r /tmp/aaa/webview2
xb@dnxb:/tmp/aaa/webview$ mkdir /tmp/aaa/webview2; cp -r -a !(\.git) /tmp/aaa/webview2        
cp: will not create hard link '/tmp/aaa/webview2/webview' to directory '/tmp/aaa/webview2/.'
cp: cannot copy a directory, '..', into itself, '/tmp/aaa/webview2'
xb@dnxb:/tmp/aaa/webview$ l /tmp/aaa/webview2                                         
total 24K
39331773 -rw-rw-r-- 1 xiaobai xiaobai ?    0 Jul  27 05:07 y
39331774 drwxrwxr-x 2 xiaobai xiaobai ? 4.0K Jul  27 05:39 !yes/
39331775 drwxrwxr-x 2 xiaobai xiaobai ? 4.0K Jul  27 05:39 webview2/
39331771 drwxrwxr-x 2 xiaobai xiaobai ? 4.0K Jul  27 05:43 .git/
39331772 drwxrwxr-x 2 xiaobai xiaobai ? 4.0K Jul  27 05:43 ss/
39331757 drwxrwxr-x 4 xiaobai xiaobai ? 4.0K Jul  27 05:44 ../
39331770 drwxrwxr-x 6 xiaobai xiaobai ? 4.0K Jul  27 05:44 ./
xb@dnxb:/tmp/aaa/webview$

이중 슬래시 \\도 작동하지 않습니다.

xb@dnxb:/tmp/aaa/webview$ rm -r /tmp/aaa/webview2
xb@dnxb:/tmp/aaa/webview$ mkdir /tmp/aaa/webview2; cp -r -a !(\\.git) /tmp/aaa/webview2
xb@dnxb:/tmp/aaa/webview$ l /tmp/aaa/webview2
total 20K
39331773 -rw-rw-r-- 1 xiaobai xiaobai ?    0 Jul  27 05:07 y
39331774 drwxrwxr-x 2 xiaobai xiaobai ? 4.0K Jul  27 05:39 !yes/
39331771 drwxrwxr-x 2 xiaobai xiaobai ? 4.0K Jul  27 05:43 .git/
39331772 drwxrwxr-x 2 xiaobai xiaobai ? 4.0K Jul  27 05:43 ss/
39331757 drwxrwxr-x 4 xiaobai xiaobai ? 4.0K Jul  27 05:44 ../
39331770 drwxrwxr-x 5 xiaobai xiaobai ? 4.0K Jul  27 05:44 ./
xb@dnxb:/tmp/aaa/webview$ 

나는 이것이 효과가 있다는 것을 알았습니다.

xb@dnxb:/tmp/aaa/webview$ rm -r /tmp/aaa/webview2
xb@dnxb:/tmp/aaa/webview$ mkdir /tmp/aaa/webview2; cp -r -a !(.git|.|..) /tmp/aaa/webview2
xb@dnxb:/tmp/aaa/webview$ l /tmp/aaa/webview2
total 16K
39331772 -rw-rw-r-- 1 xiaobai xiaobai ?    0 Jul  27 05:07 y
39331773 drwxrwxr-x 2 xiaobai xiaobai ? 4.0K Jul  27 05:39 !yes/
39331771 drwxrwxr-x 2 xiaobai xiaobai ? 4.0K Jul  27 05:43 ss/
39331757 drwxrwxr-x 4 xiaobai xiaobai ? 4.0K Jul  27 05:45 ../
39331770 drwxrwxr-x 4 xiaobai xiaobai ? 4.0K Jul  27 05:45 ./
xb@dnxb:/tmp/aaa/webview$

왜 요점을 탈출하는 것이 직접 작동하지 않습니까? 이 경우 부정하는 올바른 방법은 무엇입니까? ( !(.git|.|..)어떤 경우에는 예상치 못한 결과가 나올 수도 있습니다.)

rsync제외하는 데 사용할 수 있다는 것을 알고 있지만 그건 내 문제가 아닙니다.

[고쳐 쓰다]

테스트 케이스에 대해 extglob 및 dotglob을 활성화했지만 원인은 아닙니다.

실패 원인은 확장 실패 때문이 아니라 !(.git)오류 ...중단 때문이라고 생각합니다. .git그리고 !(.git|.|..)그것은 이미 올바른 접근 방식이어야 합니다.

답변1

에서는 bash이 옵션이 없으면 dotglobglob이 아닌 한 숨겨진 파일이 무시됩니다.분명히(즉, 문자 그대로의 선도 .)에는 그것들이 필요합니다. 무시 .되지 않습니다 ( ..더 합리적인 쉘이 원하는 것과는 pdksh반대로 zsh) fish.

glob이 로 시작하지 않는 dotglob한 sum만 .무시됩니다 ....

extglob를 사용하여 일부 확장된 전역 연산자에 대한 지원이 bash추가되었습니다 . ksh그러나 여기에는 버그/버그 기능이 있습니다 !(...).

ksh(는 아니지만 pdksh) 및 bash에서는 점 @(.*)파일이 명시적으로 요청되는 경우가 있습니다(문서에서는 이에 대해 명시적으로 언급하지 않지만).

하지만 !(.git)파일을 클릭하라는 메시지는 표시되지 않습니다. 시뮬레이션에서 올바르게 처리 ksh하되 도트 파일을 요청한다고 가정합니다. 에도 포함됩니다 . 따라서 복사본의 일부로 복사됩니다 .zshkshbash...dotglob.git.

이 문제를 해결하려면 다음과 연결을 사용하거나 !([.]git)( 여기에서는 [.]명확하지 않음 ) 다음을 제외 하고 명시적으로 연결할 수 있습니다 ..dotglob...!(.git|.|..)

$ bash -O extglob -c 'echo !(.git)'
. .. foo .foo
$ bash -O extglob -O dotglob -c 'echo !(.git)'
. .. foo .foo
$ bash -O extglob -O dotglob -c 'echo !([.]git)'
foo .foo
$ bash -O extglob -c 'echo !(.git|.|..)'
foo .foo

후자의 경우 다른 셸에서와 마찬가지로 여기에 도트 파일을 포함하지 않도록 향후 버전에서 수정될 수 있으므로 dotglob옵션 을 추가하겠습니다 .bash

zsh자체 스프레드 연산자가 있는 이를 사용할 때 ( extendedglobBourne 호환성을 유지하기 위해 이 옵션은 기본적으로 활성화되어 있지 않습니다. kshglob해당 옵션으로 ksh glob도 지원하지만 이는 더 어색합니다) 다음을 수행합니다.

set -o extendedglob # (in my ~/.zshrc)
cp -a -- ^.git(D) target/

( 파일 이름이 로 시작하지 않을 것이라고 보장할 수 없으므로 그렇게 해야 함을 -a의미합니다 .)-r---

^.gitzshksh 와 동일합니다 !(.git). 이 glob 만 포함합니다 (D)(의 도트 파일은 포함하지 않음 )....

답변2

기본적으로 셸에는 "." 확장이 포함되지 않습니다. Run을 shopt -s dotglob사용하면 셸 확장에 "."이 포함됩니다.

dotglob
    If set, Bash includes filenames beginning with a ‘.’ in the results of 
    filename expansion.

Shopt 내장 매뉴얼 페이지

관련 정보