Let's say I have this files:
xb@dnxb:/tmp/aaa/webview$ tree -F -C -a . . ├── .git/ ├── ss/ ├── y └── !yes/ 3 directories, 1 file xb@dnxb:/tmp/aaa/webview$ Negate the !yes is working fine by escape the ! with \:
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$ But !(.git) not working:
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$ Escape . with \ not working:
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$ Double slash \\ not working either:
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$ And I found this working:
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$ Why direct escape dot not working ? And what's the proper way to negate in this case ? (I doubt !(.git|.|..) will get unexpected result in some cases).
Note that I know rsync can be used to exclude, but it's not my question.
[UPDATE]
I did enabled extglob and dotglob for my test case, they're not the cause.
I think the reason of !(.git) failed is because of . and .. error and abort, not because of .git expansion was failed. And !(.git|.|..) should be the correct way already.
shopt -s extglobenabled for the!negation operator to be recognised. None of mybashshells has that enabled by default.