Skip to main content
added 72 characters in body
Source Link
Stéphane Chazelas
  • 586.5k
  • 96
  • 1.1k
  • 1.7k

In bash, without the dotglob option, hidden files are ignored unless the glob explicitly (that is with a literal leading .) asks for them. And . and .. are not ignored (contrary to what more sensible shells like pdksh, zsh or fish do).

With dotglob, only . and .. are ignored unless the glob starts with ..

With extglob, bash adds support for some of ksh extended glob operators. However, here with a bug/misfeature when it comes to the !(...) one.

In both ksh (though not pdksh) and bash, @(.*) is one case where you explicitly request dotfiles (though the documentation doesn't make that clear).

But in !(.git) you're not requesting dotfiles. ksh and zsh in ksh emulation handle it correctly, but bash presumes you're requesting dotfiles. And that includes . and .. even with dotglob. So .git will be copied as part of the copying of ..

To work around that, you can use !([.]git) (here [.] makes the . not explicit) in combination with dotglob, or exclude . and .. explicitly with !(.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 

In the latter case, I would still add the dotglob option because bash in a future version may be fixed to stop including dotfiles here like in other shells.

As I use zsh which has its own extended operators (with the extendedglob option not enabled by default to keep Bourne compatibility; it also supports ksh globs with the kshglob option but those are more awkward), I'd do:

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

(note that -a implies -r and you need the -- as we can't guarantee file names won't start with -).

^.git is zsh's equivalent of ksh's !(.git). (D) to include dotfiles (but never . nor ..) for that glob only.

In bash, without the dotglob option, hidden files are ignored unless the glob explicitly (that is with a literal leading .) asks for them. And . and .. are not ignored (contrary to what more sensible shells like pdksh, zsh or fish do).

With dotglob, only . and .. are ignored unless the glob starts with ..

With extglob, bash adds support for some of ksh extended glob operators. However, here with a bug/misfeature when it comes to the !(...) one.

In both ksh and bash, @(.*) is one case where you explicitly request dotfiles.

But in !(.git) you're not requesting dotfiles. ksh and zsh in ksh emulation handle it correctly, but bash presumes you're requesting dotfiles. And that includes . and .. even with dotglob. So .git will be copied as part of the copying of ..

To work around that, you can use !([.]git) (here [.] makes the . not explicit) in combination with dotglob, or exclude . and .. explicitly with !(.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 

In the latter case, I would still add the dotglob option because bash in a future version may be fixed to stop including dotfiles here like in other shells.

As I use zsh which has its own extended operators (with the extendedglob option not enabled by default to keep Bourne compatibility; it also supports ksh globs with the kshglob option but those are more awkward), I'd do:

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

(note that -a implies -r and you need the -- as we can't guarantee file names won't start with -).

^.git is zsh's equivalent of ksh's !(.git). (D) to include dotfiles (but never . nor ..) for that glob only.

In bash, without the dotglob option, hidden files are ignored unless the glob explicitly (that is with a literal leading .) asks for them. And . and .. are not ignored (contrary to what more sensible shells like pdksh, zsh or fish do).

With dotglob, only . and .. are ignored unless the glob starts with ..

With extglob, bash adds support for some of ksh extended glob operators. However, here with a bug/misfeature when it comes to the !(...) one.

In both ksh (though not pdksh) and bash, @(.*) is one case where you explicitly request dotfiles (though the documentation doesn't make that clear).

But in !(.git) you're not requesting dotfiles. ksh and zsh in ksh emulation handle it correctly, but bash presumes you're requesting dotfiles. And that includes . and .. even with dotglob. So .git will be copied as part of the copying of ..

To work around that, you can use !([.]git) (here [.] makes the . not explicit) in combination with dotglob, or exclude . and .. explicitly with !(.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 

In the latter case, I would still add the dotglob option because bash in a future version may be fixed to stop including dotfiles here like in other shells.

As I use zsh which has its own extended operators (with the extendedglob option not enabled by default to keep Bourne compatibility; it also supports ksh globs with the kshglob option but those are more awkward), I'd do:

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

(note that -a implies -r and you need the -- as we can't guarantee file names won't start with -).

^.git is zsh's equivalent of ksh's !(.git). (D) to include dotfiles (but never . nor ..) for that glob only.

added 110 characters in body
Source Link
Stéphane Chazelas
  • 586.5k
  • 96
  • 1.1k
  • 1.7k

In bash, without the dotglob option, hidden files are ignored unless the glob explicitly (that is with a literal leading .) asks for them. And . and .. are not ignored (contrary to what more sensible shells like pdksh, zsh or fish do).

With dotglob, only . and .. are ignored unless the glob starts with ..

With extglob, bash adds support for some of ksh extended glob operators. However, here with a bug/misfeature when it comes to the !(...) one.

In both ksh and bash, @(.*) is one case where you explicitly request dotfiles.

But in !(.git) you're not requesting dotfiles. ksh and zsh in ksh emulation handle it correctly, but bash presumes you're requesting dotfiles. And that includes . and .. even with dotglob. So .git will be copied as part of the copying of ..

To work around that, you can use !([.]git) (here [.] makes the . not explicit) in combination with dotglob, or exclude . and .. explicitly with !(.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 

In the latter case, I would still add the dotglob option because bash in a future version may be fixed to stop including dotfiles here like in other shells.

As I use zsh which has its own extended operators (with the extendedglob option not enabled by default to keep Bourne compatibility; it also supports ksh globs with the kshglob option but those are more awkward), I'd do:

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

(note that -a implies -r and you need the -- as we can't guarantee file names won't start with -).

^.git is zsh's equivalent of ksh's !(.git). (D) to include dotfiles (but never . nor ..) for that glob only.

In bash, without the dotglob option, hidden files are ignored unless the glob explicitly (that is with a literal leading .) asks for them. And . and .. are not ignored (contrary to what more sensible shells like pdksh, zsh or fish do).

With dotglob, only . and .. are ignored unless the glob starts with ..

With extglob, bash adds support for some of ksh extended glob operators. However, here with a bug/misfeature when it comes to the !(...) one.

In both ksh and bash, @(.*) is one case where you explicitly request dotfiles.

But in !(.git) you're not requesting dotfiles. ksh and zsh in ksh emulation handle it correctly, but bash presumes you're requesting dotfiles. And that includes . and .. even with dotglob. So .git will be copied as part of the copying of ..

To work around that, you can use !([.]git) (here [.] makes the . not explicit) in combination with dotglob, or exclude . and .. explicitly with !(.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 

In the latter case, I would still add the dotglob option because bash in a future version may be fixed to stop including dotfiles here like in other shells.

As I use zsh which has its own extended operators (with the extendedglob option not enabled by default to keep Bourne compatibility; it also supports ksh globs with the kshglob option but those are more awkward), I'd do:

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

^.git is zsh's equivalent of ksh's !(.git). (D) to include dotfiles (but never . nor ..) for that glob only.

In bash, without the dotglob option, hidden files are ignored unless the glob explicitly (that is with a literal leading .) asks for them. And . and .. are not ignored (contrary to what more sensible shells like pdksh, zsh or fish do).

With dotglob, only . and .. are ignored unless the glob starts with ..

With extglob, bash adds support for some of ksh extended glob operators. However, here with a bug/misfeature when it comes to the !(...) one.

In both ksh and bash, @(.*) is one case where you explicitly request dotfiles.

But in !(.git) you're not requesting dotfiles. ksh and zsh in ksh emulation handle it correctly, but bash presumes you're requesting dotfiles. And that includes . and .. even with dotglob. So .git will be copied as part of the copying of ..

To work around that, you can use !([.]git) (here [.] makes the . not explicit) in combination with dotglob, or exclude . and .. explicitly with !(.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 

In the latter case, I would still add the dotglob option because bash in a future version may be fixed to stop including dotfiles here like in other shells.

As I use zsh which has its own extended operators (with the extendedglob option not enabled by default to keep Bourne compatibility; it also supports ksh globs with the kshglob option but those are more awkward), I'd do:

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

(note that -a implies -r and you need the -- as we can't guarantee file names won't start with -).

^.git is zsh's equivalent of ksh's !(.git). (D) to include dotfiles (but never . nor ..) for that glob only.

deleted 1 character in body
Source Link
Stéphane Chazelas
  • 586.5k
  • 96
  • 1.1k
  • 1.7k

In bash, without the dotglob option, hidden files are ignored unless the glob explicitly (that is with a literal leading .) asks for them. And . and .. are not ignored (contrary to what more sensible shells like pdksh, zsh or fish do).

With dotglob, only . and .. are ignored unless the glob starts with ..

With extglob, bash adds support for some of ksh extended glob operators. However, here with a bug/misfeature when it comes to the !(...) one.

In both ksh and bash, @(.*) is one case where you explicitly request dotfiles.

But in !(.git) you're not requesting dotfiles. ``kshandkshzsh and inzshksh in emulation handle it correctly, butkshbash emulation handle it correctly, but presumes you're requesting dotfiles. And that includesbash presumes you're requesting dotfiles. And that includes and... and even with..dotglob even with . So dotglob.git So will be copied as part of the copying of.git.` will be copied as part of the copying of ..

To work around that, you can use !([.]git) (here [.] makes the . not explicit) in combination with dotglob, or exclude . and .. explicitly with !(.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 

In the latter case, I would still add the dotglob option because bash in a future version may be fixed to stop including dotfiles here like in other shells.

As I use zsh which has its own extended operators (with the extendedglob option not enabled by default to keep Bourne compatibility; it also supports ksh globs with the kshglob option but those are more awkward), I'd do:

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

^.git is zsh's equivalent of ksh's !(.git). (D) to include dotfiles (but never . nor ..) for that glob only.

In bash, without the dotglob option, hidden files are ignored unless the glob explicitly (that is with a literal leading .) asks for them. And . and .. are not ignored (contrary to what more sensible shells like pdksh, zsh or fish do).

With dotglob, only . and .. are ignored unless the glob starts with ..

With extglob, bash adds support for some of ksh extended glob operators. However, here with a bug/misfeature when it comes to the !(...) one.

In both ksh and bash, @(.*) is one case where you explicitly request dotfiles.

But in !(.git) you're not requesting dotfiles. ``kshandzshinkshemulation handle it correctly, butbashpresumes you're requesting dotfiles. And that includes.and..even withdotglob. So .gitwill be copied as part of the copying of.`.

To work around that, you can use !([.]git) (here [.] makes the . not explicit) in combination with dotglob, or exclude . and .. explicitly with !(.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 

In the latter case, I would still add the dotglob option because bash in a future version may be fixed to stop including dotfiles here like in other shells.

In bash, without the dotglob option, hidden files are ignored unless the glob explicitly (that is with a literal leading .) asks for them. And . and .. are not ignored (contrary to what more sensible shells like pdksh, zsh or fish do).

With dotglob, only . and .. are ignored unless the glob starts with ..

With extglob, bash adds support for some of ksh extended glob operators. However, here with a bug/misfeature when it comes to the !(...) one.

In both ksh and bash, @(.*) is one case where you explicitly request dotfiles.

But in !(.git) you're not requesting dotfiles. ksh and zsh in ksh emulation handle it correctly, but bash presumes you're requesting dotfiles. And that includes . and .. even with dotglob. So .git will be copied as part of the copying of ..

To work around that, you can use !([.]git) (here [.] makes the . not explicit) in combination with dotglob, or exclude . and .. explicitly with !(.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 

In the latter case, I would still add the dotglob option because bash in a future version may be fixed to stop including dotfiles here like in other shells.

As I use zsh which has its own extended operators (with the extendedglob option not enabled by default to keep Bourne compatibility; it also supports ksh globs with the kshglob option but those are more awkward), I'd do:

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

^.git is zsh's equivalent of ksh's !(.git). (D) to include dotfiles (but never . nor ..) for that glob only.

Source Link
Stéphane Chazelas
  • 586.5k
  • 96
  • 1.1k
  • 1.7k
Loading