What does `.[].foo[]` do in bash? Why does it match `..`?

The name of the pictureThe name of the pictureThe name of the pictureClash Royale CLAN TAG#URR8PPP











up vote
16
down vote

favorite
1












Look at the following:



$ echo ..aliases
..
$ echo ..foo
..
$ echo ..
..
$ echo ..xyz
..
$ echo .xyz.xyz
.xyz.xyz
$ echo .xyz.
.xyz.


Apparently this seems to be globbing something, but I don’t understand how the result comes together. From my understanding is an empty character class. It would be intuitive if



  • it matched only the empty string; in this case, I’d expect bash to reproduce in its entirety since nothing matches it in this directory, but also match things like ..aliases (in the first example),

  • or nothing at all; in this case, I’d expect bash to reproduce the string in total, too.

This is with GNU bash, version 4.4.23(1)-release.










share|improve this question



























    up vote
    16
    down vote

    favorite
    1












    Look at the following:



    $ echo ..aliases
    ..
    $ echo ..foo
    ..
    $ echo ..
    ..
    $ echo ..xyz
    ..
    $ echo .xyz.xyz
    .xyz.xyz
    $ echo .xyz.
    .xyz.


    Apparently this seems to be globbing something, but I don’t understand how the result comes together. From my understanding is an empty character class. It would be intuitive if



    • it matched only the empty string; in this case, I’d expect bash to reproduce in its entirety since nothing matches it in this directory, but also match things like ..aliases (in the first example),

    • or nothing at all; in this case, I’d expect bash to reproduce the string in total, too.

    This is with GNU bash, version 4.4.23(1)-release.










    share|improve this question

























      up vote
      16
      down vote

      favorite
      1









      up vote
      16
      down vote

      favorite
      1






      1





      Look at the following:



      $ echo ..aliases
      ..
      $ echo ..foo
      ..
      $ echo ..
      ..
      $ echo ..xyz
      ..
      $ echo .xyz.xyz
      .xyz.xyz
      $ echo .xyz.
      .xyz.


      Apparently this seems to be globbing something, but I don’t understand how the result comes together. From my understanding is an empty character class. It would be intuitive if



      • it matched only the empty string; in this case, I’d expect bash to reproduce in its entirety since nothing matches it in this directory, but also match things like ..aliases (in the first example),

      • or nothing at all; in this case, I’d expect bash to reproduce the string in total, too.

      This is with GNU bash, version 4.4.23(1)-release.










      share|improve this question















      Look at the following:



      $ echo ..aliases
      ..
      $ echo ..foo
      ..
      $ echo ..
      ..
      $ echo ..xyz
      ..
      $ echo .xyz.xyz
      .xyz.xyz
      $ echo .xyz.
      .xyz.


      Apparently this seems to be globbing something, but I don’t understand how the result comes together. From my understanding is an empty character class. It would be intuitive if



      • it matched only the empty string; in this case, I’d expect bash to reproduce in its entirety since nothing matches it in this directory, but also match things like ..aliases (in the first example),

      • or nothing at all; in this case, I’d expect bash to reproduce the string in total, too.

      This is with GNU bash, version 4.4.23(1)-release.







      bash shell wildcards






      share|improve this question















      share|improve this question













      share|improve this question




      share|improve this question








      edited Aug 14 at 10:46









      Jeff Schaller

      32.4k849110




      32.4k849110










      asked Aug 11 at 16:16









      Jonas Schäfer

      8441722




      8441722




















          2 Answers
          2






          active

          oldest

          votes

















          up vote
          25
          down vote



          accepted










          The [ starts a set. A set is terminated by ]. But there is a way to have ] as part of the set, and that is to specify the ] as the first character. As an empty set doesn't make any sense, this is not ambiguous.



          So your examples are basically all a dot followed by a set that contains a dot, therefore it matches two dots.



          The later examples don't find any files and are therefore returned verbatim.






          share|improve this answer





























            up vote
            4
            down vote













            Only quoted strings are not subject to globbing:



            $ echo "..aliases"
            ..aliases


            But un-quoted strings are subject to globbing. An unquoted string that contains an * or a ? or (valid) (bracket expression) will be modified by the list of files that match it. In the same way as a * will transform into all the files in the matching directory and a ? will match files of only one character, a (valid) will match files with the characters inside the brackets. A dot is a valid character:



            $ echo a[.]b
            a[.]b

            $ touch "a.b"
            $ echo a[.]b
            a.b


            To be able to match a ] it should be the first character inside the brackets:



            $ touch "a]b"
            $ ls a]b
            a]b


            An empty bracket expression makes no sense (and is not expanded):



            $ touch ab
            $ ls ab
            ls: cannot access 'ab': No such file or directory


            That is why this works:



            $ touch a]c abc afc azc a:c a?c aoc 
            $ ls abfz:?]c
            abc a:c a?c a]c afc azc


            For [ the idea is similar:



            $ touch a[c
            $ ls a[c
            a[c


            but it could be at any position in a bracket expression:



            $ ls abf[z:?]c
            abc a:c a?c a[c a]c afc azc

            $ ls abfz:?c
            abc a:c a?c a[c a]c afc azc


            The string you posted ..foo will match a dot followed by either a ], a ., a f, a o or a [. It is similar to:



            $ echo a.fooc
            a[c a]c afc aoc


            And it will match as follows:



            $ touch .] .f .o .[ .a .b .z

            $ echo ..foo
            .. .[ .] .f .o


            Note that the directory entry .. does not need to be created as it exists inside every directory by default. But a simple dot . won’t be matched by a glob as it needs to be matched explicitly (by actually using a dot).



            But that will not match ..aliases as the bracket expression will only match one character. To match several characters you need to use a * (anything):



            $ touch ..a ..l ..i ..aliases ..alias ..ali
            $ echo ..aliases
            .. .[ .] .a

            $ echo ..aliases*
            .. .[ .] .a ..a ..ali ..alias ..aliases ..i ..l





            share|improve this answer






















              Your Answer







              StackExchange.ready(function()
              var channelOptions =
              tags: "".split(" "),
              id: "106"
              ;
              initTagRenderer("".split(" "), "".split(" "), channelOptions);

              StackExchange.using("externalEditor", function()
              // Have to fire editor after snippets, if snippets enabled
              if (StackExchange.settings.snippets.snippetsEnabled)
              StackExchange.using("snippets", function()
              createEditor();
              );

              else
              createEditor();

              );

              function createEditor()
              StackExchange.prepareEditor(
              heartbeatType: 'answer',
              convertImagesToLinks: false,
              noModals: false,
              showLowRepImageUploadWarning: true,
              reputationToPostImages: null,
              bindNavPrevention: true,
              postfix: "",
              onDemand: true,
              discardSelector: ".discard-answer"
              ,immediatelyShowMarkdownHelp:true
              );



              );













               

              draft saved


              draft discarded


















              StackExchange.ready(
              function ()
              StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f462017%2fwhat-does-foo-do-in-bash-why-does-it-match%23new-answer', 'question_page');

              );

              Post as a guest






























              2 Answers
              2






              active

              oldest

              votes








              2 Answers
              2






              active

              oldest

              votes









              active

              oldest

              votes






              active

              oldest

              votes








              up vote
              25
              down vote



              accepted










              The [ starts a set. A set is terminated by ]. But there is a way to have ] as part of the set, and that is to specify the ] as the first character. As an empty set doesn't make any sense, this is not ambiguous.



              So your examples are basically all a dot followed by a set that contains a dot, therefore it matches two dots.



              The later examples don't find any files and are therefore returned verbatim.






              share|improve this answer


























                up vote
                25
                down vote



                accepted










                The [ starts a set. A set is terminated by ]. But there is a way to have ] as part of the set, and that is to specify the ] as the first character. As an empty set doesn't make any sense, this is not ambiguous.



                So your examples are basically all a dot followed by a set that contains a dot, therefore it matches two dots.



                The later examples don't find any files and are therefore returned verbatim.






                share|improve this answer
























                  up vote
                  25
                  down vote



                  accepted







                  up vote
                  25
                  down vote



                  accepted






                  The [ starts a set. A set is terminated by ]. But there is a way to have ] as part of the set, and that is to specify the ] as the first character. As an empty set doesn't make any sense, this is not ambiguous.



                  So your examples are basically all a dot followed by a set that contains a dot, therefore it matches two dots.



                  The later examples don't find any files and are therefore returned verbatim.






                  share|improve this answer














                  The [ starts a set. A set is terminated by ]. But there is a way to have ] as part of the set, and that is to specify the ] as the first character. As an empty set doesn't make any sense, this is not ambiguous.



                  So your examples are basically all a dot followed by a set that contains a dot, therefore it matches two dots.



                  The later examples don't find any files and are therefore returned verbatim.







                  share|improve this answer














                  share|improve this answer



                  share|improve this answer








                  edited Aug 11 at 18:25









                  Jeff Schaller

                  32.4k849110




                  32.4k849110










                  answered Aug 11 at 16:20









                  RalfFriedl

                  3,6401522




                  3,6401522






















                      up vote
                      4
                      down vote













                      Only quoted strings are not subject to globbing:



                      $ echo "..aliases"
                      ..aliases


                      But un-quoted strings are subject to globbing. An unquoted string that contains an * or a ? or (valid) (bracket expression) will be modified by the list of files that match it. In the same way as a * will transform into all the files in the matching directory and a ? will match files of only one character, a (valid) will match files with the characters inside the brackets. A dot is a valid character:



                      $ echo a[.]b
                      a[.]b

                      $ touch "a.b"
                      $ echo a[.]b
                      a.b


                      To be able to match a ] it should be the first character inside the brackets:



                      $ touch "a]b"
                      $ ls a]b
                      a]b


                      An empty bracket expression makes no sense (and is not expanded):



                      $ touch ab
                      $ ls ab
                      ls: cannot access 'ab': No such file or directory


                      That is why this works:



                      $ touch a]c abc afc azc a:c a?c aoc 
                      $ ls abfz:?]c
                      abc a:c a?c a]c afc azc


                      For [ the idea is similar:



                      $ touch a[c
                      $ ls a[c
                      a[c


                      but it could be at any position in a bracket expression:



                      $ ls abf[z:?]c
                      abc a:c a?c a[c a]c afc azc

                      $ ls abfz:?c
                      abc a:c a?c a[c a]c afc azc


                      The string you posted ..foo will match a dot followed by either a ], a ., a f, a o or a [. It is similar to:



                      $ echo a.fooc
                      a[c a]c afc aoc


                      And it will match as follows:



                      $ touch .] .f .o .[ .a .b .z

                      $ echo ..foo
                      .. .[ .] .f .o


                      Note that the directory entry .. does not need to be created as it exists inside every directory by default. But a simple dot . won’t be matched by a glob as it needs to be matched explicitly (by actually using a dot).



                      But that will not match ..aliases as the bracket expression will only match one character. To match several characters you need to use a * (anything):



                      $ touch ..a ..l ..i ..aliases ..alias ..ali
                      $ echo ..aliases
                      .. .[ .] .a

                      $ echo ..aliases*
                      .. .[ .] .a ..a ..ali ..alias ..aliases ..i ..l





                      share|improve this answer


























                        up vote
                        4
                        down vote













                        Only quoted strings are not subject to globbing:



                        $ echo "..aliases"
                        ..aliases


                        But un-quoted strings are subject to globbing. An unquoted string that contains an * or a ? or (valid) (bracket expression) will be modified by the list of files that match it. In the same way as a * will transform into all the files in the matching directory and a ? will match files of only one character, a (valid) will match files with the characters inside the brackets. A dot is a valid character:



                        $ echo a[.]b
                        a[.]b

                        $ touch "a.b"
                        $ echo a[.]b
                        a.b


                        To be able to match a ] it should be the first character inside the brackets:



                        $ touch "a]b"
                        $ ls a]b
                        a]b


                        An empty bracket expression makes no sense (and is not expanded):



                        $ touch ab
                        $ ls ab
                        ls: cannot access 'ab': No such file or directory


                        That is why this works:



                        $ touch a]c abc afc azc a:c a?c aoc 
                        $ ls abfz:?]c
                        abc a:c a?c a]c afc azc


                        For [ the idea is similar:



                        $ touch a[c
                        $ ls a[c
                        a[c


                        but it could be at any position in a bracket expression:



                        $ ls abf[z:?]c
                        abc a:c a?c a[c a]c afc azc

                        $ ls abfz:?c
                        abc a:c a?c a[c a]c afc azc


                        The string you posted ..foo will match a dot followed by either a ], a ., a f, a o or a [. It is similar to:



                        $ echo a.fooc
                        a[c a]c afc aoc


                        And it will match as follows:



                        $ touch .] .f .o .[ .a .b .z

                        $ echo ..foo
                        .. .[ .] .f .o


                        Note that the directory entry .. does not need to be created as it exists inside every directory by default. But a simple dot . won’t be matched by a glob as it needs to be matched explicitly (by actually using a dot).



                        But that will not match ..aliases as the bracket expression will only match one character. To match several characters you need to use a * (anything):



                        $ touch ..a ..l ..i ..aliases ..alias ..ali
                        $ echo ..aliases
                        .. .[ .] .a

                        $ echo ..aliases*
                        .. .[ .] .a ..a ..ali ..alias ..aliases ..i ..l





                        share|improve this answer
























                          up vote
                          4
                          down vote










                          up vote
                          4
                          down vote









                          Only quoted strings are not subject to globbing:



                          $ echo "..aliases"
                          ..aliases


                          But un-quoted strings are subject to globbing. An unquoted string that contains an * or a ? or (valid) (bracket expression) will be modified by the list of files that match it. In the same way as a * will transform into all the files in the matching directory and a ? will match files of only one character, a (valid) will match files with the characters inside the brackets. A dot is a valid character:



                          $ echo a[.]b
                          a[.]b

                          $ touch "a.b"
                          $ echo a[.]b
                          a.b


                          To be able to match a ] it should be the first character inside the brackets:



                          $ touch "a]b"
                          $ ls a]b
                          a]b


                          An empty bracket expression makes no sense (and is not expanded):



                          $ touch ab
                          $ ls ab
                          ls: cannot access 'ab': No such file or directory


                          That is why this works:



                          $ touch a]c abc afc azc a:c a?c aoc 
                          $ ls abfz:?]c
                          abc a:c a?c a]c afc azc


                          For [ the idea is similar:



                          $ touch a[c
                          $ ls a[c
                          a[c


                          but it could be at any position in a bracket expression:



                          $ ls abf[z:?]c
                          abc a:c a?c a[c a]c afc azc

                          $ ls abfz:?c
                          abc a:c a?c a[c a]c afc azc


                          The string you posted ..foo will match a dot followed by either a ], a ., a f, a o or a [. It is similar to:



                          $ echo a.fooc
                          a[c a]c afc aoc


                          And it will match as follows:



                          $ touch .] .f .o .[ .a .b .z

                          $ echo ..foo
                          .. .[ .] .f .o


                          Note that the directory entry .. does not need to be created as it exists inside every directory by default. But a simple dot . won’t be matched by a glob as it needs to be matched explicitly (by actually using a dot).



                          But that will not match ..aliases as the bracket expression will only match one character. To match several characters you need to use a * (anything):



                          $ touch ..a ..l ..i ..aliases ..alias ..ali
                          $ echo ..aliases
                          .. .[ .] .a

                          $ echo ..aliases*
                          .. .[ .] .a ..a ..ali ..alias ..aliases ..i ..l





                          share|improve this answer














                          Only quoted strings are not subject to globbing:



                          $ echo "..aliases"
                          ..aliases


                          But un-quoted strings are subject to globbing. An unquoted string that contains an * or a ? or (valid) (bracket expression) will be modified by the list of files that match it. In the same way as a * will transform into all the files in the matching directory and a ? will match files of only one character, a (valid) will match files with the characters inside the brackets. A dot is a valid character:



                          $ echo a[.]b
                          a[.]b

                          $ touch "a.b"
                          $ echo a[.]b
                          a.b


                          To be able to match a ] it should be the first character inside the brackets:



                          $ touch "a]b"
                          $ ls a]b
                          a]b


                          An empty bracket expression makes no sense (and is not expanded):



                          $ touch ab
                          $ ls ab
                          ls: cannot access 'ab': No such file or directory


                          That is why this works:



                          $ touch a]c abc afc azc a:c a?c aoc 
                          $ ls abfz:?]c
                          abc a:c a?c a]c afc azc


                          For [ the idea is similar:



                          $ touch a[c
                          $ ls a[c
                          a[c


                          but it could be at any position in a bracket expression:



                          $ ls abf[z:?]c
                          abc a:c a?c a[c a]c afc azc

                          $ ls abfz:?c
                          abc a:c a?c a[c a]c afc azc


                          The string you posted ..foo will match a dot followed by either a ], a ., a f, a o or a [. It is similar to:



                          $ echo a.fooc
                          a[c a]c afc aoc


                          And it will match as follows:



                          $ touch .] .f .o .[ .a .b .z

                          $ echo ..foo
                          .. .[ .] .f .o


                          Note that the directory entry .. does not need to be created as it exists inside every directory by default. But a simple dot . won’t be matched by a glob as it needs to be matched explicitly (by actually using a dot).



                          But that will not match ..aliases as the bracket expression will only match one character. To match several characters you need to use a * (anything):



                          $ touch ..a ..l ..i ..aliases ..alias ..ali
                          $ echo ..aliases
                          .. .[ .] .a

                          $ echo ..aliases*
                          .. .[ .] .a ..a ..ali ..alias ..aliases ..i ..l






                          share|improve this answer














                          share|improve this answer



                          share|improve this answer








                          edited Aug 19 at 14:06









                          Jeff Schaller

                          32.4k849110




                          32.4k849110










                          answered Aug 11 at 22:37









                          Isaac

                          7,0321834




                          7,0321834



























                               

                              draft saved


                              draft discarded















































                               


                              draft saved


                              draft discarded














                              StackExchange.ready(
                              function ()
                              StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f462017%2fwhat-does-foo-do-in-bash-why-does-it-match%23new-answer', 'question_page');

                              );

                              Post as a guest













































































                              Popular posts from this blog

                              How to check contact read email or not when send email to Individual?

                              Bahrain

                              Postfix configuration issue with fips on centos 7; mailgun relay