次のファイルがあるとしましょう。
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.