다음 파일이 있다고 가정해 보겠습니다.
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
이 옵션이 없으면 dotglob
glob이 아닌 한 숨겨진 파일이 무시됩니다.분명히(즉, 문자 그대로의 선도 .
)에는 그것들이 필요합니다. 무시 .
되지 않습니다 ( ..
더 합리적인 쉘이 원하는 것과는 pdksh
반대로 zsh
) fish
.
glob이 로 시작하지 않는 dotglob
한 sum만 .
무시됩니다 ...
.
extglob
를 사용하여 일부 확장된 전역 연산자에 대한 지원이 bash
추가되었습니다 . ksh
그러나 여기에는 버그/버그 기능이 있습니다 !(...)
.
ksh
(는 아니지만 pdksh
) 및 bash
에서는 점 @(.*)
파일이 명시적으로 요청되는 경우가 있습니다(문서에서는 이에 대해 명시적으로 언급하지 않지만).
하지만 !(.git)
파일을 클릭하라는 메시지는 표시되지 않습니다. 시뮬레이션에서 올바르게 처리 ksh
하되 도트 파일을 요청한다고 가정합니다. 에도 포함됩니다 . 따라서 복사본의 일부로 복사됩니다 .zsh
ksh
bash
.
..
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
자체 스프레드 연산자가 있는 이를 사용할 때 ( extendedglob
Bourne 호환성을 유지하기 위해 이 옵션은 기본적으로 활성화되어 있지 않습니다. kshglob
해당 옵션으로 ksh glob도 지원하지만 이는 더 어색합니다) 다음을 수행합니다.
set -o extendedglob # (in my ~/.zshrc)
cp -a -- ^.git(D) target/
( 파일 이름이 로 시작하지 않을 것이라고 보장할 수 없으므로 그렇게 해야 함을 -a
의미합니다 .)-r
--
-
^.git
zsh
ksh 와 동일합니다 !(.git)
. 이 glob 만 포함합니다 (D)
(의 도트 파일은 포함하지 않음 )..
..
답변2
기본적으로 셸에는 "." 확장이 포함되지 않습니다. Run을 shopt -s dotglob
사용하면 셸 확장에 "."이 포함됩니다.
dotglob
If set, Bash includes filenames beginning with a ‘.’ in the results of
filename expansion.