• extglob

    From Frank Winkler@3:633/10 to All on Tuesday, February 17, 2026 12:57:06
    Hi experts !

    I'm just playing with bash's "extglob" option:

    $ shopt -s extglob
    $ echo /etc/ssh/sshd_config?(.d)
    /etc/ssh/sshd_config /etc/ssh/sshd_config.d
    $

    So far, so good. But now I want to catch the global file and potential
    custom files.

    $ echo /etc/ssh/sshd_config?(.d/*)
    /etc/ssh/sshd_config
    $

    I would accept this if there were no files in the directory but in fact,
    there is one. Where's my brain fault?

    And to my understanding, ksh behaves like this by default, right?

    Regards

    Frank


    --- PyGate Linux v1.5.11
    * Origin: Dragon's Lair, PyGate NNTP<>Fido Gate (3:633/10)
  • From Lew Pitcher@3:633/10 to All on Tuesday, February 17, 2026 14:59:20
    On Tue, 17 Feb 2026 12:57:06 +0100, Frank Winkler wrote:

    Hi experts !

    I'm just playing with bash's "extglob" option:

    $ shopt -s extglob
    $ echo /etc/ssh/sshd_config?(.d)
    /etc/ssh/sshd_config /etc/ssh/sshd_config.d
    $

    So far, so good. But now I want to catch the global file and potential custom files.

    $ echo /etc/ssh/sshd_config?(.d/*)
    /etc/ssh/sshd_config
    $

    I would accept this if there were no files in the directory but in fact, there is one. Where's my brain fault?

    According to the bash manpage,
    "If the extglob shell option is enabled using the shopt builtin, several
    extended pattern matching operators are recognized."
    ...
    " ?(pattern-list)
    Matches zero or one occurrence of the given patterns"

    Ok, so your "given pattern" is ".d/*". Do you have any files that have a
    ".d/*" suffix? I thought not.

    Try moving the /* to outside of the patternlist, as in
    echo /etc/ssh/sshd_config?(.d)/*

    HTH


    And to my understanding, ksh behaves like this by default, right?

    I have no idea, I don't use ksh. Sorry
    --
    Lew Pitcher
    "In Skills We Trust"
    Not LLM output - I'm just like this.

    --- PyGate Linux v1.5.11
    * Origin: Dragon's Lair, PyGate NNTP<>Fido Gate (3:633/10)
  • From Frank Winkler@3:633/10 to All on Tuesday, February 17, 2026 17:38:04
    On 17.02.2026 15:59, Lew Pitcher wrote:

    >Try moving the /* to outside of the patternlist, as in
    > echo /etc/ssh/sshd_config?(.d)/*

    Nice idea but this won't work either as your expression also (falsely)
    expects "sshd_config" to be a dir and hence, it will _only_ match the
    custom files. The ".d" suffix (as a dir name) _and_ the files below it
    are one common optional part of the path.

    Thanks anyway!

    Frank


    --- PyGate Linux v1.5.11
    * Origin: Dragon's Lair, PyGate NNTP<>Fido Gate (3:633/10)
  • From Lew Pitcher@3:633/10 to All on Tuesday, February 17, 2026 16:43:57
    On Tue, 17 Feb 2026 14:59:20 +0000, Lew Pitcher wrote:

    On Tue, 17 Feb 2026 12:57:06 +0100, Frank Winkler wrote:

    Hi experts !

    I'm just playing with bash's "extglob" option:

    $ shopt -s extglob
    $ echo /etc/ssh/sshd_config?(.d)
    /etc/ssh/sshd_config /etc/ssh/sshd_config.d
    $

    So far, so good. But now I want to catch the global file and potential
    custom files.

    $ echo /etc/ssh/sshd_config?(.d/*)
    /etc/ssh/sshd_config
    $

    I would accept this if there were no files in the directory but in fact,
    there is one. Where's my brain fault?

    According to the bash manpage,
    "If the extglob shell option is enabled using the shopt builtin, several
    extended pattern matching operators are recognized."
    ...
    " ?(pattern-list)
    Matches zero or one occurrence of the given patterns"

    Ok, so your "given pattern" is ".d/*". Do you have any files that have a ".d/*" suffix? I thought not.

    What might be useful is to know that POSIX has standardized the way this "globbing" works. You can read glob(7) ("man 7 glob") for all the details,
    but the piece that governs /your/ problem is
    "Globbing is applied on each of the components of a pathname separately.
    A '/' in a pathname cannot be matched by a '?' or '*' wildcard, or by a
    range like "[.-0]". A range cannot contain an explicit '/' character; this
    would lead to a syntax error."
    So, your "?(.d/*) expression cant work, because none of the components of
    a pathname may contain a '/' character, and, thus, will never match the expression.


    Try moving the /* to outside of the patternlist, as in
    echo /etc/ssh/sshd_config?(.d)/*

    HTH


    And to my understanding, ksh behaves like this by default, right?

    I have no idea, I don't use ksh. Sorry




    --
    Lew Pitcher
    "In Skills We Trust"
    Not LLM output - I'm just like this.

    --- PyGate Linux v1.5.11
    * Origin: Dragon's Lair, PyGate NNTP<>Fido Gate (3:633/10)
  • From Frank Winkler@3:633/10 to All on Tuesday, February 17, 2026 17:53:06
    On 17.02.2026 17:43, Lew Pitcher wrote:

    >So, your "?(.d/*) expression cant work, because none of the components of
    >a pathname may contain a '/' character, and, thus, will never match the
    >expression.

    Still trying to figure this out completely ...

    But what's the solution then? Isn't there a closed expression for that?
    Do I really have to use the uncool

    /etc/ssh/sshd_config /etc/ssh/sshd_config.d/*

    way?

    TIA

    Frank


    --- PyGate Linux v1.5.11
    * Origin: Dragon's Lair, PyGate NNTP<>Fido Gate (3:633/10)
  • From Janis Papanagnou@3:633/10 to All on Tuesday, February 17, 2026 18:30:25
    On 2026-02-17 17:53, Frank Winkler wrote:
    On 17.02.2026 17:43, Lew Pitcher wrote:

    So, your "?(.d/*) expression cant work, because none of the
    components of
    a pathname may contain a '/' character, and, thus, will never match the
    expression.

    And, concerning the upthread question, Kornshell behaves the same.

    Still trying to figure this out completely ...

    Simply put; don't use slashes - the special character in the Unix
    file system - in "extended" _*file globbing* patterns_ (as quoted
    by Lew).

    In Ksh you can of course still use it in _*text* pattern matching_.

    $ x='Projects/Algol68' ; [[ $x == ?(*/)Algol68 ]] && echo match
    match

    But what's the solution then? Isn't there a closed expression for that?
    Do I really have to use the uncool

    ˙ /etc/ssh/sshd_config /etc/ssh/sshd_config.d/*

    way?

    If your task is actually two-fold
    display file sshd_config by globbing
    and
    display any file under "/etc/ssh/sshd_config.d/" by globbing
    then yes.

    If you want to match _path-*strings*_ (including optional slashes)
    then do text-processing, i.e. create the path names text and grep

    find ... | grep <some-pattern-including-slahses>

    I don't think this approach is "cooler" (whatever you meant by
    "uncool"), but the concept should be clearly differentiated now.

    HTH.

    Janis


    TIA

    ˙˙˙˙Frank



    --- PyGate Linux v1.5.11
    * Origin: Dragon's Lair, PyGate NNTP<>Fido Gate (3:633/10)
  • From Richard Harnden@3:633/10 to All on Tuesday, February 17, 2026 21:16:46
    On 17/02/2026 17:30, Janis Papanagnou wrote:
    On 2026-02-17 17:53, Frank Winkler wrote:
    On 17.02.2026 17:43, Lew Pitcher wrote:

    So, your "?(.d/*) expression cant work, because none of the
    components of
    a pathname may contain a '/' character, and, thus, will never match
    the
    expression.

    And, concerning the upthread question, Kornshell behaves the same.

    Still trying to figure this out completely ...

    Simply put; don't use slashes - the special character in the Unix
    file system - in "extended" _*file globbing* patterns_ (as quoted
    by Lew).

    In Ksh you can of course still use it in _*text* pattern matching_.

    $ x='Projects/Algol68' ; [[ $x == ?(*/)Algol68 ]] && echo match
    match

    But what's the solution then? Isn't there a closed expression for
    that? Do I really have to use the uncool

    ˙˙ /etc/ssh/sshd_config /etc/ssh/sshd_config.d/*

    way?

    If your task is actually two-fold
    ˙˙ display file sshd_config by globbing
    and
    ˙˙ display any file under "/etc/ssh/sshd_config.d/" by globbing
    then yes.

    If you want to match _path-*strings*_ (including optional slashes)
    then do text-processing, i.e. create the path names text and grep

    ˙ find ... | grep <some-pattern-including-slahses>

    I don't think this approach is "cooler" (whatever you meant by
    "uncool"), but the concept should be clearly differentiated now.

    Also, do have search permisson for /etc/ssh/ssh_config.d ?




    --- PyGate Linux v1.5.11
    * Origin: Dragon's Lair, PyGate NNTP<>Fido Gate (3:633/10)
  • From Helmut Waitzmann@3:633/10 to All on Tuesday, February 17, 2026 22:08:16
    Frank Winkler <usenet@f.winkler-ka.de>:

    But what's the solution then? Isn't there a closed expression
    for that? Do I really have to use the uncool

    /etc/ssh/sshd_config /etc/ssh/sshd_config.d/*

    way?


    Yes, you do.˙ And you might use


    shopt -s nullglob


    al well (unless you are okay with surprising results if


    /etc/ssh/sshd_config.d/*


    doesn't match any pathnames).


    --- PyGate Linux v1.5.11
    * Origin: Dragon's Lair, PyGate NNTP<>Fido Gate (3:633/10)
  • From Lawrence D?Oliveiro@3:633/10 to All on Tuesday, February 17, 2026 21:49:36
    On Tue, 17 Feb 2026 17:53:06 +0100, Frank Winkler wrote:

    Do I really have to use the uncool

    /etc/ssh/sshd_config /etc/ssh/sshd_config.d/*

    ldo@theon:~> echo /etc/ssh/sshd_config{,.d/*}
    /etc/ssh/sshd_config /etc/ssh/sshd_config.d/20-systemd-userdb.conf

    Though I think the alternatives-within-braces thing is a bash-ism ...

    --- PyGate Linux v1.5.11
    * Origin: Dragon's Lair, PyGate NNTP<>Fido Gate (3:633/10)
  • From Janis Papanagnou@3:633/10 to All on Tuesday, February 17, 2026 23:27:09
    On 2026-02-17 22:49, Lawrence D?Oliveiro wrote:
    On Tue, 17 Feb 2026 17:53:06 +0100, Frank Winkler wrote:

    Do I really have to use the uncool

    /etc/ssh/sshd_config /etc/ssh/sshd_config.d/*

    ldo@theon:~> echo /etc/ssh/sshd_config{,.d/*}
    /etc/ssh/sshd_config /etc/ssh/sshd_config.d/20-systemd-userdb.conf

    Though I think the alternatives-within-braces thing is a bash-ism ...

    No, you find brace-expressions also in ksh and zsh, for example.

    But note that this is a textual expansion by the shells that is
    performed before the pattern-(here '*')-globbing is performed.

    In cases like above it's IMO horrible to read and to parse, but
    mileages may vary.

    Janis


    --- PyGate Linux v1.5.11
    * Origin: Dragon's Lair, PyGate NNTP<>Fido Gate (3:633/10)
  • From Lumin Etherlight@3:633/10 to All on Wednesday, February 18, 2026 04:42:58
    Frank Winkler <usenet@f.winkler-ka.de> writes:

    But what's the solution then? Isn't there a closed
    expression for that? Do I really have to use the
    uncool

    /etc/ssh/sshd_config /etc/ssh/sshd_config.d/*


    If I understand correctly, your problem is
    solvable without using extglob, you can just use
    brace expansions like this:

    $ echo /etc/ssh/sshd_config{,.d/*}
    /etc/ssh/sshd_config /etc/ssh/sshd_config.d/test.conf
    $

    This selects the sshd_config file, and other
    config files inside the directory sshd_config.d.
    Curly braces surround a list of comma-separated
    options for expansion, so I specified nothing (the
    empty string) as the first one, then comma, then
    .d/*, which seems to do what you want. Check the
    braces expansion section in the bash manual for
    more details.


    Best Regards,
    Lumin Etherlight

    --- PyGate Linux v1.5.11
    * Origin: Dragon's Lair, PyGate NNTP<>Fido Gate (3:633/10)
  • From Frank Winkler@3:633/10 to All on Wednesday, February 18, 2026 09:46:15
    On 17.02.2026 22:16, Richard Harnden wrote:

    >Also, do have search permisson for /etc/ssh/ssh_config.d ?

    I suppose this question is pointed to me. Answer: yes, I have :) ...

    Regards

    Frank


    --- PyGate Linux v1.5.11
    * Origin: Dragon's Lair, PyGate NNTP<>Fido Gate (3:633/10)
  • From Frank Winkler@3:633/10 to All on Wednesday, February 18, 2026 09:51:37
    On 17.02.2026 22:49, Lawrence D?Oliveiro wrote:

    > ldo@theon:~> echo /etc/ssh/sshd_config{,.d/*}
    > /etc/ssh/sshd_config /etc/ssh/sshd_config.d/20-systemd-userdb.conf
    >
    >Though I think the alternatives-within-braces thing is a bash-ism ...

    Lawrence and Lumin, that's a great idea! Thanks very much for waking me
    up ... but indeed, I wasn't aware that this also works with path names.
    So it looks like I thought just the wrong way round: I assumed "extglob"
    to work with paths and brace expansion to not do so. Funny!

    Regards

    Frank


    --- PyGate Linux v1.5.11
    * Origin: Dragon's Lair, PyGate NNTP<>Fido Gate (3:633/10)
  • From Frank Winkler@3:633/10 to All on Wednesday, February 18, 2026 09:54:14
    On 17.02.2026 22:08, Helmut Waitzmann wrote:

    >al well (unless you are okay with surprising results if
    >
    > ˙ /etc/ssh/sshd_config.d/*
    >
    >doesn't match any pathnames).

    Yes - I already faced this issue sometimes in the past ;) ...

    Regards

    Frank


    --- PyGate Linux v1.5.11
    * Origin: Dragon's Lair, PyGate NNTP<>Fido Gate (3:633/10)
  • From Frank Winkler@3:633/10 to All on Wednesday, February 18, 2026 13:43:14
    On 18.02.2026 09:51, I wrote:

    > ˙>Though I think the alternatives-within-braces thing is a bash-ism ...

    It seems that it also works with ksh but no matter if bash or ksh, it
    does need the "nullglob" feature to give the correct result.

    That's easy to do in bash but how do I combine the brace expression with
    ksh's "~(N:)" (as there is no "nullglob" option)?

    TIA

    Frank


    --- PyGate Linux v1.5.11
    * Origin: Dragon's Lair, PyGate NNTP<>Fido Gate (3:633/10)
  • From Richard Harnden@3:633/10 to All on Wednesday, February 18, 2026 14:32:24
    On 18/02/2026 12:43, Frank Winkler wrote:
    On 18.02.2026 09:51, I wrote:

    Though I think the alternatives-within-braces thing is a bash-ism ...

    It seems that it also works with ksh but no matter if bash or ksh, it
    does need the "nullglob" feature to give the correct result.

    That's easy to do in bash but how do I combine the brace expression with ksh's "~(N:)" (as there is no "nullglob" option)?


    I think I'd use find ...

    $ find /etc/ssh/sshd_config?(.d) -type f
    /etc/ssh/sshd_config
    /etc/ssh/sshd_config.d/50-redhat.conf /etc/ssh/sshd_config.d/01-permitrootlogin.conf


    --- PyGate Linux v1.5.11
    * Origin: Dragon's Lair, PyGate NNTP<>Fido Gate (3:633/10)
  • From Frank Winkler@3:633/10 to All on Wednesday, February 18, 2026 15:57:09
    On 18.02.2026 15:32, Richard Harnden wrote:

    >I think I'd use find ...
    >
    >$ find /etc/ssh/sshd_config?(.d) -type f

    Of course, this works - but the idea was to do it shell-internally.

    Regards

    Frank


    --- PyGate Linux v1.5.11
    * Origin: Dragon's Lair, PyGate NNTP<>Fido Gate (3:633/10)
  • From Lawrence D?Oliveiro@3:633/10 to All on Wednesday, February 18, 2026 21:12:26
    On Wed, 18 Feb 2026 09:51:37 +0100, Frank Winkler wrote:

    ... I wasn't aware that [alternatives-within-braces] also works with
    path names.

    The alternatives-within-braces syntax is handled during parsing of the
    command syntax, before we get to wildcard expansion and actual command execution. At this stage, the command parser has no idea what the
    words it is processing mean: whether they?re file names, or just
    special keywords that might mean something to the specific command, or
    what.

    So of course the syntax will work with anything, path names or not.

    --- PyGate Linux v1.5.11
    * Origin: Dragon's Lair, PyGate NNTP<>Fido Gate (3:633/10)