Tilde expansion bug in associative array assignments?
I am seeing this potential regression on code checked out from https://git.savannah.gnu.org/git/bash.git at version ec8113b: $ ./configure $ make $ echo "$BASH_VERSION" 5.2.15(1)-release $ declare -A associative_array=([key]=~/Desktop) $ ls -d "${associative_array[key]}" ls: cannot access '~/Desktop': No such file or directory but: $ ls -d ~/Desktop /home/marco/Desktop On my previous version 5.1.4(1)-release the tilde expanded just fine. Marco Ippolito maroloc...@gmail.com
alias expansion with functions in non-interactive mode
Configuration Information [Automatically generated, do not change]: Machine: i686 OS: linux-gnu Compiler: gcc Compilation CFLAGS: -DPROGRAM='bash' -DCONF_HOSTTYPE='i686' -DCONF_OSTYPE='linux- uname output: Linux rogue.fortresstech.com 2.6.22-2-686 #1 SMP Fri Aug 31 00:24:01 Machine Type: i686-pc-linux-gnu Bash Version: 3.2 Patch Level: 33 Release Status: release Description: I couldn't find any information on it, but I'm noticing alias expansion is not happening in non-interactive mode within a function with expanded_aliases turned on. Is this a know problem, or am I missing something? If I remove this from the function it works as expected. Repeat-By: : cat test.sh #!/bin/bash function foo { shopt -s expand_aliases alias ls='ls -l' ls / } foo : bash -x test.sh + foo + shopt -s expand_aliases + alias 'ls=ls -l' + ls / < should be "ls -l /" Thanks, Marco Fonseca
Re: Changing the way bash expands associative array subscripts
> Examples are more for the texinfo documentation; the man page is big > enough already. What goes in the man page Vs in the texinfo documentation, please?
"$(echo "x'" '{1,2}')" performs brace expansion, even though it should not
Configuration Information [Automatically generated, do not change]: Machine: x86_64 OS: linux-gnu Compiler: gcc Compilation CFLAGS: -DPROGRAM='bash' -DCONF_HOSTTYPE='x86_64' -DCONF_OSTYPE='linux-gnu' -DCONF_MACHTYPE='x86_64-unknown-linux-gnu' -DCONF_VENDOR='unknown' -DLOCALEDIR='/usr/share/locale' -DPACKAGE='bash' -DSHELL -DHAVE_CONFIG_H -I. -I. -I./include -I./lib -march=x86-64 -mtune=generic -O2 -pipe -fstack-protector --param=ssp-buffer-size=4 -D_FORTIFY_SOURCE=2 -DDEFAULT_PATH_VALUE='/usr/local/bin:/usr/bin:/bin:/usr/local/sbin:/usr/sbin:/sbin' -DSTANDARD_UTILS_PATH='/usr/bin:/bin:/usr/sbin:/sbin' -DSYS_BASHRC='/etc/bash.bashrc' -DSYS_BASH_LOGOUT='/etc/bash.bash_logout' uname output: Linux laptop 3.6.11-1-ARCH #1 SMP PREEMPT Tue Dec 18 08:57:15 CET 2012 x86_64 GNU/Linux Machine Type: x86_64-unknown-linux-gnu Bash Version: 4.2 Patch Level: 42 Release Status: release Description: If a double-quoted command substitution command contains a double-quoted string containing a single-quote, followed by a single-quoted string containing a brace-expansion expression, then the command to be substituted is not executed correctly. See examples below. Also tested with the following versions and produces the same behaviour: GNU bash, version 3.2.25(1)-release (x86_64-redhat-linux-gnu) Repeat-By: $ echo "$(echo "x" '{1,2}')" # Produces expected result x {1,2} $ echo "$(echo "x'" '{1,2}')" # Bug case: Add single-quote to first string, causing brace-expansion! x' 1 x' 2 $ echo $(echo "x'" '{1,2}') # Produces expected result, but unquoted! x' {1,2}
eval "{" has exit status 0
Configuration Information [Automatically generated, do not change]: Machine: x86_64 OS: linux-gnu Compiler: gcc Compilation CFLAGS: -DPROGRAM='bash' -DCONF_HOSTTYPE='x86_64' -DCONF_OSTYPE='linux-gnu' -DCONF_MACHTYPE='x86_64-unknown-linux-gnu' -DCONF_VENDOR='unknown' -DLOCALEDIR='/nix/store/mm631h09mj964hm9q04l5fd8vw12j1mm-bash-3.2-p39/share/locale' -DPACKAGE='bash' -DSHELL -DHAVE_CONFIG_H -I. -I. -I./include -I./lib -g -O2 uname output: Linux mail.desk 2.6.25.17-default #1 SMP Tue Oct 7 23:48:14 UTC 2008 x86_64 GNU/Linux Machine Type: x86_64-unknown-linux-gnu Bash Version: 3.2 Patch Level: 39 Release Status: release Description: I'd say eval "{" should have non zero exit status.. Maybe it should behave like this function and return exit status 1 ? eval(){ # does not work in sh e="$(type eval | { read; while read line; do echo $line; done })" # get this fuction text unset eval; # unset this function local evalSucc="failure" eval "evalSucc=ok;""$1" eval "$e" # define this function again [ $evalSucc = "failure" ] && return 1 }
-e test description in the GNU Bash 5.0 man page from 7 December 2018
In the GNU Bash 5.0 man page from 7 December 2018 the -e test is documented as such: -e file True if file exists. When "file" is a symlink name to a non-existing target, the -e test fails, and this may be surprising from just reading the documentation. By contrast, POSIX describes the same test as follows: -e pathname True if pathname resolves to an existing directory entry. False if pathname cannot be resolved. POSIX provides an indication as to the potential failure of the test in contexts in which symlink *resolution* is performed. It might be beneficial to reword this Linux man page. It *may* also be beneficial to change the use of "file" in the GNU man page to refer to pathnames, as POSIX does, so that the distinction between "files" and "regular files" be more explicit. Observe this test description on the GNU man page, for example: -f file True if file exists and is a regular file. Here is a sample GNU script illustrating the tests alluded to above: #! /usr/bin/env bash # Run me on GNU/Linux cd "$(mktemp --directory)" touch existing_file ln --symbolic existing_file symlink_to_existing_file ln --symbolic non_existing_file symlink_to_non_existing_file ln --symbolic symlink_to_existing_file symlink_to_symlink_to_existing_file ln --symbolic symlink_to_non_existing_file symlink_to_unresolvable_symlink { for pathname in \ existing_file \ symlink_to_existing_file \ symlink_to_non_existing_file \ symlink_to_symlink_to_existing_file \ symlink_to_unresolvable_symlink do if [[ -e $pathname ]]; then existence=exists else existence='does not exist' fi printf '[[ -e %s ]] \x1f -> \x1f %s\n' "$pathname" "$existence" done; } | column -t -s $'\x1f' Outputs: [[ -e existing_file ]] -> exists [[ -e symlink_to_existing_file ]] -> exists [[ -e symlink_to_non_existing_file ]] -> does not exist [[ -e symlink_to_symlink_to_existing_file ]] -> exists [[ -e symlink_to_unresolvable_symlink ]] -> does not exist
Re: -e test description in the GNU Bash 5.0 man page from 7 December 2018
On 21/10/2019 11:11, Andreas Schwab wrote: On Okt 21 2019, Marco Ippolito wrote: In the GNU Bash 5.0 man page from 7 December 2018 the -e test is documented as such: -e file True if file exists. When "file" is a symlink name to a non-existing target, the -e test fails, and this may be surprising from just reading the documentation. It also says: Unless otherwise specified, primaries that operate on files follow sym- bolic links and operate on the target of the link, rather than the link itself. Andreas. I still personally find this overloading of the term "file" to refer to: (1) a generic operand of those primaries we'll call "file", be it an actual file or something else (2) an actual file somewhat unnecessarily ambiguous compared to the POSIX version. As a minor point, when I read the POSIX's wording of "resolves to an existing directory entry", I find it intuitive, possibly from familiarity with other Computer Science contexts like DNS in which look-ups happen in a chain, that the word "resolves" might entail recursion, as in the case I highlighted in code, where a link's target was another symlink. When I read "follow", especially paired with the singular "the target of the link" (not "of the links" or "of the link chain" or similia - and by the way, why use "link" here and not "symlink"? to give the name "link" to a "chain of symlinks"?), I am left wondering for a moment if that implies recursion or not, which is something I did not, subjectively, wonder about when reading the alternative word "resolves". After all, the man page for readlink uses the word "follow" to read a link's target but it makes the point of being explicit about recursive application for the canonicalisation options, as if it weren't automatic to think of "following a link" as "following it... until the end": -f, --canonicalize canonicalize by following every symlink in every component of the given name recursively; all but the last component must exist -e, --canonicalize-existing canonicalize by following every symlink in every component of the given name recursively, all components must exist -m, --canonicalize-missing canonicalize by following every symlink in every component of the given name recursively, without requirements on components existence If following is meant to be understood as "always to the end of the symlink chain", it seems redundant to say to follow _every_ symlink and to do so _recursively_. So, in summary: - file still looks less precise than pathname to me - (minor point) resolution seems like an elegant term to copy from POSIX to indicate the recursive process, whereby to "follow", especially paired with a singular noun (i.e. link), might be more confusing to some
Add support for array .pop()
Bash has elegant and powerful constructs like `mapfile', yet it is missing something as easy as an array "pop". Extract the last value of an array at the same time as removing it from the array. Is this the best one can do? $ a=(1 2 3); v=${a[-1]}; unset 'a[-1]'; printf '%s\n' "$v" "${a[@]}" The 2-step approach gets tiresome after a while. For positional parameters, it _does_ have `shift'... ... maybe it could add a `pop`, somehow?