• Is there a POSIX compliant way of turning a "HH:MM:SS" formatted string

    From lbrtchx@tutamail.com@21:1/5 to All on Thu Jul 17 23:40:01 2025
    Video durations are formatted in youtube's .info.json files as "HH:MM:SS"; so, I went monkey and did the conversion myself, but I got two errors which I can't make sense of whatsoever with only two values:

    _HHMMSS="19:09"
    _HHMMSS="19:08"
    IFS=$(echo -en "\n\b"); _SEKNDS_AR=($(echo "${_HHMMSS}" | tr ':' '\n')); _SEKNDS_ARL=${#_SEKNDS_AR[@]}
    if [[ ${_SEKNDS_ARL} -eq 2 ]]; then
    _SEKNDS=$(( 60 * ${_SEKNDS_AR[0]} )); _SEKNDS=$(( _SEKNDS + ${_SEKNDS_AR[1]} )) echo "// __ \$_SEKNDS: |${_SEKNDS}|"
    fi

    bash: _SEKNDS + 08: value too great for base (error token is "08")
    ~
    yet, it works for _HHMMSS={"3:54:14", "20:01", "20:00", "19:07", "19:06", "19:05", ... } and all other similar conversion?!

    lbrtchx

    <html>
    <head>
    <meta http-equiv="content-type" content="text/html; charset=UTF-8">
    </head>
    <body>
    <div dir="auto">Video durations are formatted in youtube's .info.json files as "HH:MM:SS"; so, I went monkey and did the conversion myself, but I got two errors which I can't make sense of whatsoever with only two values:<br></div><div dir="auto"><br></
    <div dir="auto">_HHMMSS="19:09"<br></div><div dir="auto">_HHMMSS="19:08"<br></div><div dir="auto">IFS=$(echo -en "\n\b"); _SEKNDS_AR=($(echo "${_HHMMSS}" | tr ':' '\n')); _SEKNDS_ARL=${#_SEKNDS_AR[@]}<br></div><div dir="auto">if [[ ${_SEKNDS_ARL} -eq
    2 ]]; then<br></div><div dir="auto">_SEKNDS=$(( 60 * ${_SEKNDS_AR[0]} )); _SEKNDS=$(( _SEKNDS + ${_SEKNDS_AR[1]} ))<br></div><div dir="auto">echo "// __ \$_SEKNDS: |${_SEKNDS}|"<br></div><div dir="auto">fi<br></div><div dir="auto"><br></div><div dir="
    auto">bash: _SEKNDS + 08: value too great for base (error token is "08")<br></div><div dir="auto">~<br></div><div dir="auto">yet, it works for _HHMMSS={"3:54:14", "20:01", "20:00", "19:07", "19:06", "19:05", ... } and all other similar conversion?!<br></
    <div dir="auto"><br></div><div dir="auto">lbrtchx<br></div> </body> </html>

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Dan Purgert@21:1/5 to lbrtchx@tutamail.com on Fri Jul 18 00:00:01 2025
    On Jul 17, 2025, lbrtchx@tutamail.com wrote:
    Video durations are formatted in youtube's .info.json files as "HH:MM:SS"; so, I went monkey and did the conversion myself, but I got two errors which I can't make sense of whatsoever with only two values:

    _HHMMSS="19:09"
    _HHMMSS="19:08"
    IFS=$(echo -en "\n\b"); _SEKNDS_AR=($(echo "${_HHMMSS}" | tr ':' '\n')); _SEKNDS_ARL=${#_SEKNDS_AR[@]}
    if [[ ${_SEKNDS_ARL} -eq 2 ]]; then
    _SEKNDS=$(( 60 * ${_SEKNDS_AR[0]} )); _SEKNDS=$(( _SEKNDS + ${_SEKNDS_AR[1]} ))
    echo "// __ \$_SEKNDS: |${_SEKNDS}|"
    fi

    bash: _SEKNDS + 08: value too great for base (error token is "08")

    It thinks you're using Octal. I have this in my notes (egregiously
    stolen from http://mywiki.wooledge.org ... but I don't have the exact
    page, and it's throwing 502 at me ..)



    August is the month when all your scripts break because you placed
    $(date +%m) in a variable and tried to do arithmetic with it, without
    removing the leading zeros. 08 is considered octal. Use $((10#$month))
    to force decimal, or strip the zero.


    Hope it helps :)


    --
    |_|O|_|
    |_|_|O| Github: https://github.com/dpurgert
    |O|O|O| PGP: DDAB 23FB 19FA 7D85 1CC1 E067 6D65 70E5 4CE7 2860

    -----BEGIN PGP SIGNATURE-----

    iQIzBAEBCgAdFiEE3asj+xn6fYUcweBnbWVw5UznKGAFAmh5cFEACgkQbWVw5Uzn KGBGVg/9EX31WWAuyjkJDrygAJqXYQ9fxw6djEMAX4PPzm1z5z00z/CT05SNCZ4S tXrmSXMy0LQzl5YIGglqy2nDjr+njaPT9jnKB9tywiDexhwca24g0mbqOT4RDQn1 yL2wEXOL8xveXI0Qi7XK1UvSeSk4uftxomQeqOFRLW89UyFHpNi7Qcf4SDly7eph itsbY6a4Xbp38NlMPnDRxrmFnu5jaeD+5x2RSpN0auYclU8z9n/i4VwgMz4vGm03 7FGSre3T7C+qt/4ofPcpR6OMyLFCVL4KzFSXYaYXb3PaMB3vPSEZg8HuQIw7x7ni yV4CMfOpAluV3p+0kowBa+cmm65aN7IaeRLl0FqQ27/YZ2YEhvu3f/h6a+oZCr2G Yucm6uAoz/SBwttIpcDjVOdaNcSHAWmXygZW3XekBLWQxPFg8R2QCP8ZqoIJyJu6 wEeg1wXof0L+ZK9Nl7ufToYgt4GbR75qd2eI2obnTLTCUeIJBJVbH5lnEud4/g8w OhcIC9jbjIdDknBn+ATfElQDulbN6RHIeYOxoM8h3dKnlv+Ohd+MfkTdzaC7FqX5 jBj5hOerydQ4V/64RvZToq1YTiJjVrVkBKGqYWS/X7118wq6ZUb9WqS4tHVb3AUw GnUCEenAQg1aIq3YnY0VGHg31sTi6rh2A0MeFb51ybyEnTpW3BI=
    =1rRF
    -----END PGP SIGNATURE-----

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Us
  • From Alain D D Williams@21:1/5 to lbrtchx@tutamail.com on Fri Jul 18 00:10:01 2025
    On Thu, Jul 17, 2025 at 11:39:02PM +0200, lbrtchx@tutamail.com wrote:
    Video durations are formatted in youtube's .info.json files as "HH:MM:SS"; so, I went monkey and did the conversion myself, but I got two errors which I can't make sense of whatsoever with only two values:

    _HHMMSS="19:09"

    seconds=$( date --date="1 january 1970 $_HHMMSS" "+%s" )

    --
    Alain Williams
    Linux/GNU Consultant - Mail systems, Web sites, Networking, Programmer, IT Lecturer.
    +44 (0) 787 668 0256 https://www.phcomp.co.uk/
    Parliament Hill Computers. Registration Information: https://www.phcomp.co.uk/Contact.html
    #include <std_disclaimer.h>

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From lbrtchx@tutamail.com@21:1/5 to All on Fri Jul 18 00:20:01 2025
    OK, it makes some more sense now. The range of digits in the octal system is from 0 to 7, so it would complain with "08" and "09" (but not with "10" which would then be "8" in octal), but why would command line utilities assume you are encoding numeric
    values as octal? Now I notice many people have stumble on the same problem. There should be a straight forward way to encode from "HH:MM:SS" to seconds. I doubt that the date utility would assume you are computing numbers as octal.

    <html>
    <head>
    <meta http-equiv="content-type" content="text/html; charset=UTF-8">
    </head>
    <body>
    <div dir="auto"><span style="color: rgb(0, 29, 53); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2;
    word-spacing: 0px; -webkit-text-stroke-width: 0px; white-space: normal; background-color: rgb(255, 255, 255); text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial; float: none; display: inline !important;"><
    span class="" style="font-family:&quot;Google Sans&quot;, Roboto, Arial, sans-serif"><span class="" style="font-size:18px">OK, it makes some more sense now. The range of digits in the octal system is from<span>&nbsp;</span></span></span></span>0 to 7, so
    it would complain with "08" and "09" (but not with "10" which would then be "8" in octal), but why would command line utilities assume you are encoding numeric values as octal? Now I notice many people have stumble on the same problem. There should be a
    straight forward way to encode from "HH:MM:SS" to seconds. I doubt that the date utility would assume you are computing numbers as octal.<br></div> </body>
    </html>

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Alain D D Williams@21:1/5 to lbrtchx@tutamail.com on Fri Jul 18 00:50:01 2025
    On Fri, Jul 18, 2025 at 12:27:04AM +0200, lbrtchx@tutamail.com wrote:
    _HHMMSS="19:09" means 19*60 + 9 = 1149 seconds
    _HHMMSS="19:08" means 19*60 + 8 = 1148 seconds

    So: 19:09 is 19 minutes and 9 seconds ?

    It is not HHMMSS for that you should have _HHMMSS="00:19:09"

    I found a bug in my solution --- time zone problems, so setting to GMT is needed:

    _HHMMSS="19:09:00"
    seconds=$( TZ=GMT date --date="1 january 1970 $_HHMMSS" "+%s" )
    echo seconds=$seconds
    seconds=68940

    _HHMMSS="00:19:09"
    seconds=$( TZ=GMT date --date="1 january 1970 $_HHMMSS" "+%s" )
    echo seconds=$seconds
    seconds=1149

    so, it seems date is also somehow parsing that value as octal even though it is being formatted in a date friendly way. is there a way to exactly specify the encoding of the input for date?

    --
    Alain Williams
    Linux/GNU Consultant - Mail systems, Web sites, Networking, Programmer, IT Lecturer.
    +44 (0) 787 668 0256 https://www.phcomp.co.uk/
    Parliament Hill Computers. Registration Information: https://www.phcomp.co.uk/Contact.html
    #include <std_disclaimer.h>

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From lbrtchx@tutamail.com@21:1/5 to All on Fri Jul 18 00:30:01 2025
    _HHMMSS="19:09" means 19*60 + 9 = 1149 seconds
    _HHMMSS="19:08" means 19*60 + 8 = 1148 seconds

    so, it seems date is also somehow parsing that value as octal even though it is being formatted in a date friendly way. is there a way to exactly specify the encoding of the input for date?


    <html>
    <head>
    <meta http-equiv="content-type" content="text/html; charset=UTF-8">
    </head>
    <body>
    <div dir="auto">_HHMMSS="19:09" means 19*60 + 9 = 1149 seconds<br></div><div dir="auto">_HHMMSS="19:08" means 19*60 + 8 = 1148 seconds<br></div><div dir="auto"><br></div><div dir="auto">so, it seems date is also somehow parsing that value as octal even
    though it is being formatted in a date friendly way. is there a way to exactly specify the encoding of the input for date?<br></div><div dir="auto"><br></div> </body>
    </html>

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Greg Wooledge@21:1/5 to lbrtchx@tutamail.com on Fri Jul 18 01:00:01 2025
    On Thu, Jul 17, 2025 at 23:39:02 +0200, lbrtchx@tutamail.com wrote:
    Video durations are formatted in youtube's .info.json files as "HH:MM:SS";

    OK.

    _HHMMSS="19:09"
    _HHMMSS="19:08"
    IFS=$(echo -en "\n\b"); _SEKNDS_AR=($(echo "${_HHMMSS}" | tr ':' '\n')); _SEKNDS_ARL=${#_SEKNDS_AR[@]}

    Your Subject header is asking for "POSIX compliant" but you're using
    commands here that aren't POSIX compliant. echo with options isn't
    compliant, and array variables aren't either.

    If you're using array variables, then you're writing for bash, not for
    sh, and that means you can drop the "POSIX compliant" requirement.
    This means you can use $'...' to set IFS, you can use array variables,
    you can use local variables in functions, you can use parameter expansions
    that replace characters or extract substrings by character index, etc.

    if [[ ${_SEKNDS_ARL} -eq 2 ]]; then
    _SEKNDS=$(( 60 * ${_SEKNDS_AR[0]} )); _SEKNDS=$(( _SEKNDS + ${_SEKNDS_AR[1]} ))
    echo "// __ \$_SEKNDS: |${_SEKNDS}|"
    fi

    bash: _SEKNDS + 08: value too great for base (error token is "08")

    Others have explained the octal issue, so I won't dwell on it.

    As far as the code goes, I'd rather start from scratch.

    ======================================================================== #!/bin/bash
    shopt -s extglob

    # Interpret $1 (which must be in MM:SS or HH:MM:SS format) as a duration
    # and convert it to a number of seconds, which is returned in variable r. hms2sec() {
    local h m s
    case $1 in
    *:*:*) h=${1%%:*} h=${h##+(0)}
    m=${1#*:}
    s=${m#*:} s=${s##+(0)}
    m=${m%:*} m=${m##+(0)}
    ;;
    *:*) h=0
    m=${1%:*} m=${m##+(0)}
    s=${1#*:} s=${s##+(0)}
    ;;
    *) echo "unrecognized input '$1'" >&2; return 1;;
    esac

    r=$((h*3600 + m*60 + s))
    return 0
    }

    for hms in 19:09 07:08 3:06:07; do
    hms2sec "$hms"
    echo "$hms -> $r"
    done
    ========================================================================

    This is one way to tackle the problem. It's *almost* POSIX compliant;
    the bashisms here are the local variables in the function, and the +(0) extended glob for removing multiple leading zeroes.

    If you assume the input can never have multiple leading zeroes to
    remove, then you could drop both of those bashisms, and it would work
    in POSIX sh (though I'm not sure how POSIX handles empty variables
    in arithmetic expansions; you might want to add extra checks for
    empty variables and set them to 0).

    If you don't want to see an explanation of the function, you can stop
    reading here. The rest is just tutorial.

    - - - - - - - - -

    The function receives one input variable (positional parameter 1) and
    takes it apart, and then does arithmetic using the parts.

    The first thing it does is examine the format, to see whether it's
    HH:MM:SS (with two colons) or MM:SS (with one colon). If it's not
    either of those, then it's considered an error, and the function
    writes a message to stderr and returns failure (1).

    In the HH:MM:SS case, which is the harder part, the extraction is done
    in four steps.

    1) The number of hours is the input string up until the first colon,
    so everything from the first colon to the end of the string is
    removed. That's the ${1%%:*} expansion. Then, any leading zeroes
    are stripped (the ${h##+(0)} expansion).

    2) The MM:SS part of the input string, which is everything after the
    first colon, is temporarily stored in the m variable. That's the
    m=${1#*:} expansion. I could have used a fourth variable to hold
    this value, but I decided to use the existing m variable.

    3) The number of seconds is the MM:SS part (which is in m) after the
    colon, so it's extracted using the s=${m#*:} expansion. Then,
    as before, the leading zeroes are stripped.

    4) Finally, the number of minutes is extracted from the MM:SS part
    using m=${m%:*} and then the leading zeroes are stripped.

    In the MM:SS case (one colon), the extraction is simpler:

    1) The number of hours is always 0.

    2) The number of minutes is the input string up to the colon,
    so it's extracted with m=${1%:*} and then leading zeroes are
    stripped.

    3) The number of seconds is the input string after the colon,
    so it's extracted with s=${1#*:} and then leading zeroes are
    stripped.

    After the input has been separated into parts, with leading zeroes
    stripped to avoid the octal problem, calculating the number of
    seconds is straightforward arithmetic. The output value is stored in
    the variable r, which is *not* local to the function. This gives
    the caller control over whether they want to use their own local r
    variable, or to let r be global. Either way, there is no command
    substitution, which means there's no forked subshell process.

    The entire script is written in pure shell code, and does not fork
    any processes.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Greg Wooledge@21:1/5 to Alain D D Williams on Fri Jul 18 01:40:01 2025
    On Fri, Jul 18, 2025 at 00:31:17 +0100, Alain D D Williams wrote:
    On Fri, Jul 18, 2025 at 01:21:08AM +0200, lbrtchx@tutamail.com wrote:
    OK, the Math is right, but the assumptions made by date aren't smart. I "overtested" your one liner with the kinds of input you would grab using jq from youtube .info.json files

    and to my amazement, when you only have two semicolon separated values, the bash date utility assumes the first chunk to be the hours and the second the minutes!:

    Colon, not semicolon, yes?

    I am not at all surprised. It could have been either HH:MM or MM:SS. I think that HH:MM is reasonable/correct - but I will not argue. But you now know how it
    interprets it so simply detect the NN:NN case and append :00

    Yeah, I'm not surprised either. The design of GNU date's -d parsing is to interpret strings that are written by or for humans. Also remember, these
    are *times* and not durations. If a human writes "The party is at 7:30",
    they almost certainly mean 19:30:00 rather than 7.5 minutes past midnight.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Alain D D Williams@21:1/5 to lbrtchx@tutamail.com on Fri Jul 18 01:40:01 2025
    On Fri, Jul 18, 2025 at 01:21:08AM +0200, lbrtchx@tutamail.com wrote:
    OK, the Math is right, but the assumptions made by date aren't smart. I "overtested" your one liner with the kinds of input you would grab using jq from youtube .info.json files

    and to my amazement, when you only have two semicolon separated values, the bash date utility assumes the first chunk to be the hours and the second the minutes!:

    I am not at all surprised. It could have been either HH:MM or MM:SS. I think that HH:MM is reasonable/correct - but I will not argue. But you now know how it
    interprets it so simply detect the NN:NN case and append :00

    --
    Alain Williams
    Linux/GNU Consultant - Mail systems, Web sites, Networking, Programmer, IT Lecturer.
    +44 (0) 787 668 0256 https://www.phcomp.co.uk/
    Parliament Hill Computers. Registration Information: https://www.phcomp.co.uk/Contact.html
    #include <std_disclaimer.h>

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From lbrtchx@tutamail.com@21:1/5 to All on Fri Jul 18 01:30:02 2025
    OK, the Math is right, but the assumptions made by date aren't smart. I "overtested" your one liner with the kinds of input you would grab using jq from youtube .info.json files and to my amazement, when you only have two semicolon separated values, the
    bash date utility assumes the first chunk to be the hours and the second the minutes!:

    _HHMMSS="19:09:00"
    seconds=$( TZ=GMT date --date="1 january 1970 $_HHMMSS" "+%s" )
    echo "// __ \$_HHMMSS|$_HHMMSS|, seconds=$seconds"

    _HHMMSS="19:08:00"
    seconds=$( TZ=GMT date --date="1 january 1970 $_HHMMSS" "+%s" )
    echo "// __ \$_HHMMSS|$_HHMMSS|, seconds=$seconds"

    _HHMMSS="00:19:09"
    seconds=$( TZ=GMT date --date="1 january 1970 $_HHMMSS" "+%s" )
    echo "// __ \$_HHMMSS|$_HHMMSS|, seconds=$seconds"

    _HHMMSS="00:19:08"
    seconds=$( TZ=GMT date --date="1 january 1970 $_HHMMSS" "+%s" )
    echo "// __ \$_HHMMSS|$_HHMMSS|, seconds=$seconds"

    _HHMMSS="19:09"
    seconds=$( TZ=GMT date --date="1 january 1970 $_HHMMSS" "+%s" )
    echo "// __ \$_HHMMSS|$_HHMMSS|, seconds=$seconds"

    _HHMMSS="19:08"
    seconds=$( TZ=GMT date --date="1 january 1970 $_HHMMSS" "+%s" )
    echo "// __ \$_HHMMSS|$_HHMMSS|, seconds=$seconds"
    // __ $_HHMMSS|19:09:00|, seconds=68940
    // __ $_HHMMSS|19:08:00|, seconds=68880
    // __ $_HHMMSS|00:19:09|, seconds=1149
    // __ $_HHMMSS|00:19:08|, seconds=1148
    // __ $_HHMMSS|19:09|, seconds=68940
    // __ $_HHMMSS|19:08|, seconds=68880
    $ 
    ~
     I will have to go over, learn from Greg's reply when I get the chance. I still think that there should be a way to make what I need straight forward using date's own formatting.
     lbrtchx

    <html>
    <head>
    <meta http-equiv="content-type" content="text/html; charset=UTF-8">
    </head>
    <body>
    <div dir="auto">OK, the Math is right, but the assumptions made by date aren't smart. I "overtested" your one liner with the kinds of input you would grab using jq from youtube .info.json files and to my amazement, when you only have two semicolon
    separated values, the bash date utility assumes the first chunk to be the hours and the second the minutes!:<br></div><div dir="auto"><br></div><div dir="auto">_HHMMSS="19:09:00"<br></div><div dir="auto">seconds=$( TZ=GMT date --date="1 january 1970 $_
    HHMMSS" "+%s" )<br></div><div dir="auto">echo "// __ \$_HHMMSS|$_HHMMSS|, seconds=$seconds"<br></div><div dir="auto"><br></div><div dir="auto">_HHMMSS="19:08:00"<br></div><div dir="auto">seconds=$( TZ=GMT date --date="1 january 1970 $_HHMMSS" "+%s" )<br><
    /div><div dir="auto">echo "// __ \$_HHMMSS|$_HHMMSS|, seconds=$seconds"<br></div><div dir="auto"><br></div><div dir="auto">_HHMMSS="00:19:09"<br></div><div dir="auto">seconds=$( TZ=GMT date --date="1 january 1970 $_HHMMSS" "+%s" )<br></div><div dir="auto"
    echo "// __ \$_HHMMSS|$_HHMMSS|, seconds=$seconds"<br></div><div dir="auto"><br></div><div dir="auto">_HHMMSS="00:19:08"<br></div><div dir="auto">seconds=$( TZ=GMT date --date="1 january 1970 $_HHMMSS" "+%s" )<br></div><div dir="auto">echo "// __ \$_
    HHMMSS|$_HHMMSS|, seconds=$seconds"<br></div><div dir="auto"><br></div><div dir="auto">_HHMMSS="19:09"<br></div><div dir="auto">seconds=$( TZ=GMT date --date="1 january 1970 $_HHMMSS" "+%s" )<br></div><div dir="auto">echo "// __ \$_HHMMSS|$_HHMMSS|,
    seconds=$seconds"<br></div><div dir="auto"><br></div><div dir="auto">_HHMMSS="19:08"<br></div><div dir="auto">seconds=$( TZ=GMT date --date="1 january 1970 $_HHMMSS" "+%s" )<br></div><div dir="auto">echo "// __ \$_HHMMSS|$_HHMMSS|, seconds=$seconds"<br></
    <div dir="auto">// __ $_HHMMSS|19:09:00|, seconds=68940<br></div><div dir="auto">// __ $_HHMMSS|19:08:00|, seconds=68880<br></div><div dir="auto">// __ $_HHMMSS|00:19:09|, seconds=1149<br></div><div dir="auto">// __ $_HHMMSS|00:19:08|, seconds=1148<
    </div><div dir="auto">// __ $_HHMMSS|19:09|, seconds=68940<br></div><div dir="auto">// __ $_HHMMSS|19:08|, seconds=68880<br></div><div dir="auto">$&nbsp;<br></div><div dir="auto">~<br></div><div dir="auto">&nbsp;I will have to go over, learn from Greg'
    s reply when I get the chance. I still think that there should be a way to make what I need straight forward using date's own formatting.<br></div><div dir="auto">&nbsp;lbrtchx</div><div dir="auto"><br></div> </body>
    </html>

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Dan Purgert@21:1/5 to lbrtchx@tutamail.com on Fri Jul 18 02:00:01 2025
    On Jul 18, 2025, lbrtchx@tutamail.com wrote:
    OK, it makes some more sense now. The range of digits in the octal
    system is from 0 to 7, so it would complain with "08" and "09" (but
    not with "10" which would then be "8" in octal), but why would command
    line utilities assume you are encoding numeric values as octal? Now I
    notice many people have stumble on the same problem. There should be a straight forward way to encode from "HH:MM:SS" to seconds. I doubt
    that the date utility would assume you are computing numbers as
    octal.

    As I recall, this is a holdover from languages that predate C that an
    explicit leading zero indicated octal notation.

    Decimal 7 => 7
    Octal 7 => 07
    Character 7 => '7'

    --
    |_|O|_|
    |_|_|O| Github: https://github.com/dpurgert
    |O|O|O| PGP: DDAB 23FB 19FA 7D85 1CC1 E067 6D65 70E5 4CE7 2860

    -----BEGIN PGP SIGNATURE-----

    iQIzBAEBCgAdFiEE3asj+xn6fYUcweBnbWVw5UznKGAFAmh5jbMACgkQbWVw5Uzn KGDK7w/8DPgkaJaM0OeTLB9R1YaHNJ1/JU+HE8z23du/WWScJ26ou8s1MurUtxuh 9UxMrKdcuPLyElzU7XGCzgoYZKcvA4R8wufrsL0VzHY/icxJ7IAnOoXOpIRIBvtf EeUaOEB4OVUkhOM0sW7KHQcnpsHaL8lQWCDADIvDnffepxyMKLkFGY5XRPBnmHGO /jmHrfTR0jba2PNnsGrac97OT8JGLjoe2n/b1aiuYt2IR2mxwYuZbD34h+kBoiXc yF4MOp7Ym0DuTskJ4gEqbpshDW8h74Ih1eJTs45Q8dyx7lma7JqXwbqq5wYO0Mjc +Q9uhfB+SE1hk8V9gJk5Ciemvzkj4kQCG9mlmhT7+DGmbRh1DLSzUpe5johGmv9p EgZegQckG1gShhcGKVHtY0zgk8YMtPTWPbDbh5p3pfp4ZDr4HTIftM5z5wXh6w0A HUQOVs/6EHzNjlSJ1oMWfdJtA+eA5t/bxvv38xznqfggtqJypceBzqO6ePYKw8Cb Fnqpc7+Ylr+OnYl/pCRP4z7sHMo1of5P2IJdZnsZUAS1KZ6t7r5jd4PRt7qv3rUR DGACzhaPWMKy0+lIOrvhMfd++J0Hx6w4/+sq+3gnPH97wjWUKXthskLhR12VAf77 wGNtdUxUK1twGNJYDQ1LanNO2UXv7nF9AiuTEqr6WjTfvYOOU7I=
    =qw3V
    -----END PGP SIGNATURE-----

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Us
  • From tomas@tuxteam.de@21:1/5 to Dan Purgert on Fri Jul 18 07:40:01 2025
    On Thu, Jul 17, 2025 at 07:56:39PM -0400, Dan Purgert wrote:
    On Jul 18, 2025, lbrtchx@tutamail.com wrote:
    OK, it makes some more sense now. The range of digits in the octal
    system is from 0 to 7, so it would complain with "08" and "09" (but
    not with "10" which would then be "8" in octal), but why would command
    line utilities assume you are encoding numeric values as octal? Now I notice many people have stumble on the same problem. There should be a straight forward way to encode from "HH:MM:SS" to seconds. I doubt
    that the date utility would assume you are computing numbers as
    octal.

    As I recall, this is a holdover from languages that predate C that an explicit leading zero indicated octal notation.

    Decimal 7 => 7
    Octal 7 => 07
    Character 7 => '7'

    Exactly: the leading zero signals octal notation (as a leading 0x would
    signal hexadecimal). You can override the base with a prefix. It's all
    in man 1 bash, section "ARITHMETIC EVALUATION":

    Integer constants follow the C language definition, without
    suffixes or character constants. Constants with a leading 0
    are interpreted as octal numbers. A leading 0x or 0X denotes
    hexadecimal. Otherwise, numbers take the form [base#]n, where the
    optional base is a decimal number between 2 and 64 representing
    the arithmetic base, and n is a number in that base. If base#
    is omitted, then base 10 is used. When specifying n, if a
    non-digit is required, the digits greater than 9 are represented
    by the lowercase letters, the uppercase letters, @, and _, in
    that order. If base is less than or equal to 36, lowercase and
    uppercase letters may be used interchangeably to represent numbers
    between 10 and 35.

    Cheers
    --
    t

    -----BEGIN PGP SIGNATURE-----

    iF0EABECAB0WIQRp53liolZD6iXhAoIFyCz1etHaRgUCaHnc2AAKCRAFyCz1etHa Rr3PAJ96HD6qe60W31iByekyfzrF+EFKqACeOnuLnsburH9eHwbwilrZVtWWi/w=
    =gHI3
    -----END PGP SIGNATURE-----

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Michael@21:1/5 to Greg Wooledge on Fri Jul 18 12:50:01 2025
    On Friday, July 18, 2025 12:52:03 AM CEST, Greg Wooledge wrote:
    As far as the code goes, I'd rather start from scratch.

    just out of curiosity:

    i don't like fix global return values (like $r in your code). i'd rather
    give the function a variable name to put the result in.

    do you have any objections to doing this in bash?: ======================================================================== #!/bin/bash

    # $1: name of variable to put the result in
    # $2...#n: parameters optional for whatever the function does
    myfunc ()
    {
    # do something... or not...

    printf -v "$1" "%s..." "..." ...
    }

    myfunc "my_result" ...

    echo "$my_result" ========================================================================

    an yes, i don't care about POSIX compliance.

    greetings...

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Greg Wooledge@21:1/5 to Michael on Fri Jul 18 13:40:01 2025
    On Fri, Jul 18, 2025 at 12:34:36 +0200, Michael wrote:
    On Friday, July 18, 2025 12:52:03 AM CEST, Greg Wooledge wrote:
    As far as the code goes, I'd rather start from scratch.

    just out of curiosity:

    i don't like fix global return values (like $r in your code). i'd rather
    give the function a variable name to put the result in.

    do you have any objections to doing this in bash?: ======================================================================== #!/bin/bash

    # $1: name of variable to put the result in
    # $2...#n: parameters optional for whatever the function does
    myfunc ()
    {
    # do something... or not...

    printf -v "$1" "%s..." "..." ...
    }

    Bash 4.3 and higher have nameref variables, so you could also do
    something like:

    myfunc() {
    local -n ret="$1"
    local a b c
    a=... b=... c=...
    ret=$((a*b + c))
    }

    The advantage of nameref variables is that they can also refer to
    arrays as well as strings. If you need to return an array, this is
    the way you'd want to go (unless you're targeting older systems).

    Both ways work, with one important caveat. If the function doesn't use
    any local variables at all, then these approaches work perfectly well.
    However, things start to become ugly if the function uses local variables
    and the caller passes a variable name that collides with one of them.

    A demonstration, using the printf variant:

    hobbit:~$ f() { local a=computed_output; printf -v "$1" "$a"; }
    hobbit:~$ unset -v x; f x; declare -p x
    declare -- x="computed_output"
    hobbit:~$ unset -v a; f a; declare -p a
    bash: declare: a: not found

    When $1 is "a", the output value is written to the variable named "a",
    which is the function's local variable.

    There is unfortunately *no* way at all to define a local reference to
    a variable in a different scope. You're at the mercy of bash's
    dynamic scoping rules.

    The only workaround for that is to make all of your local variables
    obscure, so that the caller is unlikely to duplicate them. Prefixing
    every local variable with something like _myfunc_ (underscore,
    function name, underscore) is one way to ensure a lack of collisions,
    as long as the caller doesn't go out of their way to cause breakage.
    Obviously, this makes the code uglier.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Michael Paoli@21:1/5 to lbrtchx@tutamail.com on Fri Jul 18 22:20:01 2025
    E.g.:
    printf 01:02:03 | (IFS=: read h m s; printf '%s\n' $(( $((h * 3600)) +
    $((m * 60)) + $s )))

    On Thu, Jul 17, 2025 at 2:39 PM <lbrtchx@tutamail.com> wrote:

    Video durations are formatted in youtube's .info.json files as "HH:MM:SS"; so, I went monkey and did the conversion myself, but I got two errors which I can't make sense of whatsoever with only two values:

    _HHMMSS="19:09"
    _HHMMSS="19:08"
    IFS=$(echo -en "\n\b"); _SEKNDS_AR=($(echo "${_HHMMSS}" | tr ':' '\n')); _SEKNDS_ARL=${#_SEKNDS_AR[@]}
    if [[ ${_SEKNDS_ARL} -eq 2 ]]; then
    _SEKNDS=$(( 60 * ${_SEKNDS_AR[0]} )); _SEKNDS=$(( _SEKNDS + ${_SEKNDS_AR[1]} ))
    echo "// __ \$_SEKNDS: |${_SEKNDS}|"
    fi

    bash: _SEKNDS + 08: value too great for base (error token is "08")
    ~
    yet, it works for _HHMMSS={"3:54:14", "20:01", "20:00", "19:07", "19:06", "19:05", ... } and all other similar conversion?!

    lbrtchx

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Greg Wooledge@21:1/5 to Michael Paoli on Fri Jul 18 22:40:02 2025
    On Fri, Jul 18, 2025 at 13:16:17 -0700, Michael Paoli wrote:
    E.g.:
    printf 01:02:03 | (IFS=: read h m s; printf '%s\n' $(( $((h * 3600)) +
    $((m * 60)) + $s )))

    You still need to strip leading zeroes.

    hobbit:~$ echo 01:08:09 | (IFS=: read h m s; printf '%s\n' $(( $((h * 3600)) +
    $((m * 60)) + $s )))
    bash: 08: value too great for base (error token is "08")

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Michael Paoli@21:1/5 to greg@wooledge.org on Sat Jul 19 04:10:01 2025
    echo $(( $(echo 07:08:09 | sed -e 's/^0*\([0-9]\)/3600 * \1 + /;s/:0*\([0-9]:\)/60 * \1/;s/:0*\([0-9]\)$/ + \1/;') ))

    On Fri, Jul 18, 2025 at 1:31 PM Greg Wooledge <greg@wooledge.org> wrote:

    On Fri, Jul 18, 2025 at 13:16:17 -0700, Michael Paoli wrote:
    E.g.:
    printf 01:02:03 | (IFS=: read h m s; printf '%s\n' $(( $((h * 3600)) +
    $((m * 60)) + $s )))

    You still need to strip leading zeroes.

    hobbit:~$ echo 01:08:09 | (IFS=: read h m s; printf '%s\n' $(( $((h * 3600)) +
    $((m * 60)) + $s )))
    bash: 08: value too great for base (error token is "08")


    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Greg Wooledge@21:1/5 to Michael Paoli on Sat Jul 19 04:10:01 2025
    On Fri, Jul 18, 2025 at 18:59:06 -0700, Michael Paoli wrote:
    echo $(( $(echo 07:08:09 | sed -e 's/^0*\([0-9]\)/3600 * \1 + /;s/:0*\([0-9]:\)/60 * \1/;s/:0*\([0-9]\)$/ + \1/;') ))

    This one is missing some * operators. You're only capturing a single
    digit in each segment, but there could be two digits (or maybe even
    more in the first segment).

    hobbit:~$ echo $(( $(echo 07:18:19 | sed -e 's/^0*\([0-9]\)/3600 * \1 + /;s/:0*\([0-9]:\)/60 * \1/;s/:0*\([0-9]\)$/ + \1/;') ))
    bash: 3600 * 7 + :18:19 : syntax error: operand expected (error token is ":18:19 ")

    Realistically, though, why are people so *bent* on writing "one-liners"?
    It's less efficient and less readable than the straightforward code.

    Longer code is not worse. It's often better.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Michael Paoli@21:1/5 to greg@wooledge.org on Sat Jul 19 06:10:01 2025
    echo \
    $((
    $(
    d12='\([0-9]\{1,2\}\)'
    echo 09:10:11 |
    sed -e '
    s/^/ /
    s/:/ /g
    s/ 0*\([0-9]\)/ \1/g
    '" s/^ $d12 $d12 $d12"'$/3600 * \1 + 60 * \2 + \3/
    '
    )
    ))

    On Fri, Jul 18, 2025 at 7:09 PM Greg Wooledge <greg@wooledge.org> wrote:

    On Fri, Jul 18, 2025 at 18:59:06 -0700, Michael Paoli wrote:
    echo $(( $(echo 07:08:09 | sed -e 's/^0*\([0-9]\)/3600 * \1 + /;s/:0*\([0-9]:\)/60 * \1/;s/:0*\([0-9]\)$/ + \1/;') ))

    This one is missing some * operators. You're only capturing a single
    digit in each segment, but there could be two digits (or maybe even
    more in the first segment).

    hobbit:~$ echo $(( $(echo 07:18:19 | sed -e 's/^0*\([0-9]\)/3600 * \1 + /;s/:0*\([0-9]:\)/60 * \1/;s/:0*\([0-9]\)$/ + \1/;') ))
    bash: 3600 * 7 + :18:19 : syntax error: operand expected (error token is ":18:19 ")

    Realistically, though, why are people so *bent* on writing "one-liners"?
    It's less efficient and less readable than the straightforward code.

    Longer code is not worse. It's often better.


    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Greg Wooledge@21:1/5 to Max Nikulin on Sat Jul 19 14:30:01 2025
    On Sat, Jul 19, 2025 at 10:14:49 +0700, Max Nikulin wrote:
    A mathematical trick may be used instead even if external processes like sed are considered as undesired overhead

    for i in 0 09 008 59 080; do i1=1$i; i2=2$i; echo "$i = $((2*i1 - i2))";
    done

    0 = 0
    09 = 9
    008 = 8
    59 = 59
    080 = 80

    Oh, I like this one. I'm gonna add that to my wiki.


    On Fri, Jul 18, 2025 at 21:08:09 -0700, Michael Paoli wrote:
    echo \
    $((
    $(
    d12='\([0-9]\{1,2\}\)'
    echo 09:10:11 |
    sed -e '
    s/^/ /
    s/:/ /g
    s/ 0*\([0-9]\)/ \1/g
    '" s/^ $d12 $d12 $d12"'$/3600 * \1 + 60 * \2 + \3/
    '
    )
    ))

    I don't like this one as much. It's better than the original one-liner
    (both because it's actually correct -- I think! -- and because it's in
    a format that's a little bit easier to read), but it still looks like
    it was written by someone who is bound and determined to use sed for this,
    no matter how difficult it may be.

    Also, the use of [0-9]\{1,2\} for the first segment means you're
    hard-capping this to 99:59:59 and will never be able to handle 100:23:45.
    That might be OK, or not. I don't know whether there are any restrictions
    on the durations the OP is dealing with. I would've used \{1,\} to
    remove the two-digit limit, if I had to do it this way.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Tim Woodall@21:1/5 to lbrtchx@tutamail.com on Sun Jul 20 00:40:01 2025
    On Thu, 17 Jul 2025, lbrtchx@tutamail.com wrote:

    Video durations are formatted in youtube's .info.json files as "HH:MM:SS"; so, I went monkey and did the conversion myself, but I got two errors which I can't make sense of whatsoever with only two values:

    _HHMMSS="19:09"
    _HHMMSS="19:08"
    IFS=$(echo -en "\n\b"); _SEKNDS_AR=($(echo "${_HHMMSS}" | tr ':' '\n')); _SEKNDS_ARL=${#_SEKNDS_AR[@]}
    if [[ ${_SEKNDS_ARL} -eq 2 ]]; then
    _SEKNDS=$(( 60 * ${_SEKNDS_AR[0]} )); _SEKNDS=$(( _SEKNDS + ${_SEKNDS_AR[1]} ))
    echo "// __ \$_SEKNDS: |${_SEKNDS}|"
    fi

    bash: _SEKNDS + 08: value too great for base (error token is "08")
    ~
    yet, it works for _HHMMSS={"3:54:14", "20:01", "20:00", "19:07", "19:06", "19:05", ... } and all other similar conversion?!

    lbrtchx

    Not sure about posix but:

    date -u -d '1/1/70 12:08' '+%s'
    43680

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Greg Wooledge@21:1/5 to Max Nikulin on Sun Jul 20 04:50:01 2025
    On Sun, Jul 20, 2025 at 09:02:37 +0700, Max Nikulin wrote:
    I have no idea to which degree the following is portable:

    strip_zeroes() { zeroes="${1%%[!0]*}"; printf '%s\n' "${1#"$zeroes"}"; }

    That's POSIX compliant. It's very similar to the first examples on <https://mywiki.wooledge.org/BashFAQ/067>:

    # POSIX
    junk=${var%%[! ]*} # remove all but leading spaces
    var=${var#"$junk"} # remove leading spaces from original string

    junk=${var##*[! ]} # remove all but trailing spaces
    var=${var%"$junk"} # remove trailing spaces from original string

    I have a strong dislike for functions that "return" things by writing
    to stdout, and expect you to capture that output using a command
    substitution, because every command substitution creates a forked process.
    Not to mention the fact that command substitution alters the captured
    output (by stripping all trailing newlines).

    But that's just me. I know that functions writing to stdout are
    considered "normal" in sh scripting, and that I'm fighting an uphill
    battle.

    However what
    I am really afraid of is

    https://mywiki.wooledge.org/BashPitfalls#pf46
    46. read num; echo $((num+1))

    Always validate your input (see BashFAQ/054) before using num in an arithmetic context as it allows code injection.

    $ echo 'a[$(echo injection >&2)]' | bash -c 'read num; echo $((num+1))' injection
    1

    Yes. Bash is a complete disaster when it comes to safety.

    To avoid code injections, you always have to look at your input sources
    and decide how trustworthy they are. If your input source is $(date +%d)
    or something similar, you can be pretty sure it won't ever give you
    unsafe values. But if you're reading input from a user, you'll want to validate it before you do anything else.

    And make sure your validation is stringy, *NOT* something mathy like:
    [[ $x = $((x)) ]] || die "..."

    Examples of acceptable validation:
    [[ $x = +([0-9]) ]] || die "input must be a number"

    hmsglob='+([0-9]):[0-9][0-9]?(:[0-9][0-9])'
    [[ $input = $hmsglob ]] || die "input must be M:SS or H:MM:SS"

    JavaScript (browser dev tools console)
    009 === 9 // => true
    parseInt("009") // => 9
    010 === 8 // => true
    parseInt("010") // => 10

    I won't even ask.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Michael Paoli@21:1/5 to greg@wooledge.org on Sun Jul 20 06:10:01 2025
    The original
    https://lists.debian.org/debian-user/2025/07/msg00407.html
    specified HH:MM:SS format for input, nothing more, nothing
    less. And sure, we should validate input and, e.g. throw error if input
    isn't valid. But if we want to accept additional, well, that should
    also be in the earlier specification. Also, the earlier context,
    YouTube video durations, also not likely we'll be dealing
    with > 99H 59M 59S video durations. And quick search seems to suggest
    YouTube currently has a max. video duration of 12 hours.

    And sed and awk are POSIX, so using those is POSIX, so long as we
    restrict ourselves to specified POSIX functionality.

    And yes, could do it entirely within POSIX shell, no external commands/programs at all, though that may be fair bit more code.
    Others have suggested, e.g. python. Certainly python or perl or the
    like could be used, code would be more concise, but system overhead
    would generally be significantly larger. sed and awk are comparatively lightweight, and quite POSIX, though not as system efficient as doing it
    only within the shell itself, at least presuming we're already in a
    POSIX (capable) shell context.

    I also left out input validation in the interests of brevity, but of
    course that's easy to add. A more complete POSIX compliant example:

    #!/bin/sh

    # Take our HH:MM:SS format 1st and only argument,
    # convert to seconds and write that to stdout.

    set -e

    LC_ALL=C export LC_ALL

    # [ test is not guaranteed to be built-in to POSIX shell, so we'll try
    # to stick to what must be internal only.
    # same applies to echo (plus its other (potential) issues)

    case "$# $1" in
    1\ [0-9][0-9]:[0-9][0-9]:[0-9][0-9])
    :
    ;;
    *)
    1>&2 printf '%s\n' \
    "${0##*/}: usage, requires single argument in format HH:MM:SS, aborting"
    exit 1
    ;;
    esac
    h=${1%%:*}
    h=${h#0}
    hm=${1%:*}
    m=${hm#*:}
    unset hm
    m=${m#0}
    s=${1##*:}
    s=${s#0}
    printf '%s\n' $((3600 * h + 60 * m + s))

    Of course in the original post, more full context wasn't mentioned.
    So, e.g., did they want a separate standalone program for this?
    Or were they wanting to do it in existing POSIX shell program, or
    perhaps even existing interactive POSIX shell session.

    In that case they may want something a simple as a copy-paste one-liner
    that they could then easily reuse from shell history for some convenient
    bit.

    (hhmmss=09:08:07; set -e; LC_ALL=C export LC_ALL; case "$hhmmss" in [0-9][0-9]:[0-9][0-9]:[0-9][0-9]) :;; *) exit 1;; esac;
    h=${hhmmss%%:*}; h=${h#0}; hm=${hhmmss%:*}; m=${hm#*:}; unset hm;
    m=${m#0}; s=${hhmmss##*:}; s=${s#0}; printf '%s\n' $((3600 * h + 60 *
    m + s)))

    Or maybe they'd want to add similar to an existing POSIX shell program,
    with bit of suitable reformatting, and replace the exit 1 with return 1
    within a function, or some more suitable/complete error handling, and
    perhaps augment the set -e with some more general error trapping and
    handling via trap.


    On Sat, Jul 19, 2025 at 5:26 AM Greg Wooledge <greg@wooledge.org> wrote:
    On Fri, Jul 18, 2025 at 21:08:09 -0700, Michael Paoli wrote:
    echo \
    $((
    $(
    d12='\([0-9]\{1,2\}\)'
    echo 09:10:11 |
    sed -e '
    s/^/ /
    s/:/ /g
    s/ 0*\([0-9]\)/ \1/g
    '" s/^ $d12 $d12 $d12"'$/3600 * \1 + 60 * \2 + \3/
    '
    )
    ))

    I don't like this one as much. It's better than the original one-liner
    (both because it's actually correct -- I think! -- and because it's in
    a format that's a little bit easier to read), but it still looks like
    it was written by someone who is bound and determined to use sed for this,
    no matter how difficult it may be.

    Also, the use of [0-9]\{1,2\} for the first segment means you're
    hard-capping this to 99:59:59 and will never be able to handle 100:23:45. That might be OK, or not. I don't know whether there are any restrictions
    on the durations the OP is dealing with. I would've used \{1,\} to
    remove the two-digit limit, if I had to do it this way.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Greg Wooledge@21:1/5 to Michael on Mon Jul 21 14:10:02 2025
    On Mon, Jul 21, 2025 at 13:37:33 +0200, Michael wrote:
    iirc, i think i have read in your wiki to NOT have variable names with leading underscores...

    If you restrict yourself to never using variable names beginning with _
    in normal situations, then that gives you the opportunity to use it
    as a pseudo-namespace delimiter in this unusual situation.

    I'm not sure which page you're referring to specifically, but generally
    the convention is that if you begin a variable name with _ then it
    has some special meaning or significance, which is up to you to define.
    The basic idea is that if you create a variable name of this form, you
    can be fairly confident that it doesn't collide with anything, but this
    only works if you follow a consistent convention.

    If *all* your variable names begin with _ then you're just a lunatic.
    (Yes, I've seen people do this. No, I have no clue why.)

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Michael@21:1/5 to Greg Wooledge on Mon Jul 21 13:40:02 2025
    first: thank you for your valuable input!

    On Friday, July 18, 2025 1:30:27 PM CEST, Greg Wooledge wrote:
    On Fri, Jul 18, 2025 at 12:34:36 +0200, Michael wrote:
    On Friday, July 18, 2025 12:52:03 AM CEST, Greg Wooledge wrote: ...

    Bash 4.3 and higher have nameref variables, [...]

    although i was aware of nameref variables in bash, i never used them. i wonder, why... well, maybe in the future i might change to using them,
    instead of printf -v...

    The advantage of nameref variables is that they can also refer to
    arrays as well as strings. If you need to return an array, this is
    the way you'd want to go (unless you're targeting older systems).

    my oldest system is running debian 9 with bash version 4.4... so i should
    be clear in this regard... (the now ancient debian version is another topic
    we won't discuss here... ;) )

    Both ways work, with one important caveat. If the function doesn't use
    any local variables at all, then these approaches work perfectly well. However, things start to become ugly if the function uses local variables
    and the caller passes a variable name that collides with one of them.

    that is true! but hey, it's bash... maybe in some version of the future
    they come up with namespaces for functions or something equivalent. but i guess that would break a lot of scripts out there...

    There is unfortunately *no* way at all to define a local reference to
    a variable in a different scope. You're at the mercy of bash's
    dynamic scoping rules.

    i'm fully aware...

    The only workaround for that is to make all of your local variables
    obscure, so that the caller is unlikely to duplicate them. Prefixing
    every local variable with something like _myfunc_ (underscore,
    function name, underscore) is one way to ensure a lack of collisions,
    as long as the caller doesn't go out of their way to cause breakage. Obviously, this makes the code uglier.

    you're right, i agree...

    but, on a completely different topic: since you suggested a prefix '_myfunc_'...

    iirc, i think i have read in your wiki to NOT have variable names with
    leading underscores...

    greetings...

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From The Wanderer@21:1/5 to Greg Wooledge on Mon Jul 21 14:40:01 2025
    This is an OpenPGP/MIME signed message (RFC 4880 and 3156)
    On 2025-07-21 at 08:04, Greg Wooledge wrote:

    On Mon, Jul 21, 2025 at 13:37:33 +0200, Michael wrote:

    iirc, i think i have read in your wiki to NOT have variable names
    with leading underscores...

    If you restrict yourself to never using variable names beginning with
    _ in normal situations, then that gives you the opportunity to use
    it as a pseudo-namespace delimiter in this unusual situation.

    I'm not sure which page you're referring to specifically, but
    generally the convention is that if you begin a variable name with _
    then it has some special meaning or significance, which is up to you
    to define. The basic idea is that if you create a variable name of
    this form, you can be fairly confident that it doesn't collide with
    anything, but this only works if you follow a consistent convention.

    If *all* your variable names begin with _ then you're just a
    lunatic. (Yes, I've seen people do this. No, I have no clue why.)

    I have two potential guesses: one, it provides a type of indication that
    this *is* a variable, and two, it provides a visual separation of the
    *name* part of the variable from the syntactic $ prefix. The latter can
    be valuable for some people's ways of experiencing and interacting with
    code.

    I gather that some projects name C-preprocessor macros with a leading underscore for that latter reason, specifically so that when you define
    them on the command line it comes out as '-D_MACRO_NAME' rather than '-DMACRO_NAME'; the former is, at least slightly, more readable than the latter.

    My totally unfounded understanding is that this latter may be where the
    use of underscore as a prefix for identifiers comes from in the first
    place.


    And, of course, in code that might wind up including headers (etc.) from
    the Linux kernel, identifiers beginning with *two* underscores are
    (officially, AFAIK, or as officially as any of this gets) reserved for
    use *by* kernel code; non-kernel code should never try to set one.

    I *hope* that doesn't apply for anything shell-based, but at this point
    in my experience I'm reluctant to rule anything *out*.

    --
    The Wanderer

    The reasonable man adapts himself to the world; the unreasonable one
    persists in trying to adapt the world to himself. Therefore all
    progress depends on the unreasonable man. -- George Bernard Shaw


    -----BEGIN PGP SIGNATURE-----

    iQIzBAEBCgAdFiEEJCOqsZEc2qVC44pUBKk1jTQoMmsFAmh+NQQACgkQBKk1jTQo MmuGHA//W8xqkIJK++Hfk2k34xOIKNc+/rTUXpAZiZaVL4u+hatvv82rBt2PYr/Y KZhoS74oJldQn+LRSDvHdRVw9EbRYk/bHYG5KcrviCvj973BsMYOerNJ+5tbqI8Q jOXMzAXr5DpuW+SdgpP2I1T55fSku5177Bj4mOdpwZ8M6+I0ob9oHO3aTz8KHoaN n9+Kpx3GXsDmIuDfIYqwc9gLXS9jole0ytmHDkKDvzpZyQlG1lQ/eXXJg3dJzQTJ h32sHohO8RrNDIpDeP+6RbVB7Z1GLkSixhx19gLUhDdDuk5Jc11oI5tKGZeL6Gdn dG1XDv3WcX9NRmCLkyFCXnsUhKpWq8pW2u0+meL0pKgf/LsZVC87n2u07ro3Q167 yt58TLpXBX9R7FqMrBGBAJEbPhcIvxNlRFzYmJBpAfDQ1l9DCZoccNRiW6vxy9a9 Dp14Dukwskm+eJbzqlOFM+XsJgELlf1mxlvMrxYi0NixID5JgJgyXY4zy/Kz/RN7 ARfE6r3MQIBpPcmxaL8S/b6bjBuJATUy50L0bDRJGiH6SonDGy5/rXZXEkHsXB54 9Ye5kJw0o2UXyjYUGtPpqzRWiDagzqTjoetBorQ+/Yo6HOqlM84Xh+OYL9rURCQZ XSBgt2zSIrwLkJ68LB3oSTqLOG2g