Feature request - make type show that a builtin is a loadable

2022-10-23 Thread Geir Hauge
I think it's a good idea for the type builtin to distinguish between
static and loadable builtins, and for debugging scripts that use
loadable builtins, it would be useful to be able to see which file got
loaded. For example in cases where BASH_LOADABLES_PATH was
unintentionally unset or set to a wrong path.

I had a go at implementing it and cobbled together the attached patch.
It extends struct builtin with a new path field that gets set to the
path that was passed to dlopen. The type builtin then includes that path
in its output if it is set.

$ ./bash -c 'enable csv; type [ csv'
[ is a shell builtin
csv is a shell builtin (/usr/local/lib/bash/csv)
$ BASH_LOADABLES_PATH=$PWD/examples/loadables ./bash -c 'enable csv; type [ 
csv'
[ is a shell builtin
csv is a shell builtin (/Users/geirha/bash/examples/loadables/csv)

Continuing on the debugging aspect, I think it would also be useful if
enable would warn or fail if you try to enable a loadable builtin that
was built against a different bash version. The easiest is probably to
embed the bash version inside the loadable file somehow, and compare
that when loading. Giving something like:

$ enable csv
bash: enable: /usr/local/lib/bash/csv: builtin was built for bash-5.1.16

Not sure how to go about implementing that though, or if it's even a
good approach. After all, you could potentially have multiple bash
builds of the same version with different configure options, which could
potentially leave out some function the loadable builtin expects to use.

-- 
Geir Hauge
diff --git a/builtins.h b/builtins.h
index 01565935..b4c71274 100644
--- a/builtins.h
+++ b/builtins.h
@@ -57,6 +57,7 @@ struct builtin {
   char * const *long_doc;  /* NULL terminated array of strings. */
   const char *short_doc;   /* Short version of documentation. */
   char *handle;/* for future use */
+  char *path;  /* path of loadable builtin. */
 };
 
 /* Found in builtins.c, created by builtins/mkbuiltins. */
diff --git a/builtins/enable.def b/builtins/enable.def
index 27d341a6..ae861b96 100644
--- a/builtins/enable.def
+++ b/builtins/enable.def
@@ -340,6 +340,7 @@ dyn_load_builtin (list, flags, filename)
 #endif
 
   handle = 0;
+  load_path = 0;
   if (absolute_program (filename) == 0)
 {
   loadables_path = get_string_value ("BASH_LOADABLES_PATH");
@@ -353,7 +354,6 @@ dyn_load_builtin (list, flags, filename)
 #else
  handle = dlopen (load_path, RTLD_LAZY);
 #endif /* !_AIX */
- free (load_path);
}
}
 }
@@ -377,6 +377,8 @@ dyn_load_builtin (list, flags, filename)
  if (name != filename)
free (name);
}
+  if (load_path)
+free (load_path);
   return (EX_NOTFOUND);
 }
 
@@ -434,6 +436,7 @@ dyn_load_builtin (list, flags, filename)
   if (flags & SPECIAL)
b->flags |= SPECIAL_BUILTIN;
   b->handle = handle;
+  b->path = load_path ? savestring(load_path) : NULL;
 
   if (old_builtin)
{
@@ -444,6 +447,9 @@ dyn_load_builtin (list, flags, filename)
  new_builtins[new++] = b;
 }
 
+  if (load_path)
+free (load_path);
+
   if (replaced == 0 && new == 0)
 {
   free (new_builtins);
diff --git a/builtins/type.def b/builtins/type.def
index a8e47c0a..fc7099db 100644
--- a/builtins/type.def
+++ b/builtins/type.def
@@ -52,6 +52,7 @@ $END
 
 #include 
 
+#include "../builtins.h"
 #include "../bashtypes.h"
 #include "posixstat.h"
 
@@ -289,6 +290,7 @@ describe_command (command, dflags)
 }
 
   /* Command is a builtin? */
+  struct builtin *b = builtin_address_internal(command, 0);
   if (((dflags & CDESC_FORCE_PATH) == 0) && find_shell_builtin (command))
 {
   if (dflags & CDESC_TYPE)
@@ -297,6 +299,8 @@ describe_command (command, dflags)
{
  if (posixly_correct && find_special_builtin (command) != 0)
printf (_("%s is a special shell builtin\n"), command);
+ else if (b->path)
+   printf (_("%s is a shell builtin (%s)\n"), command, b->path);
  else
printf (_("%s is a shell builtin\n"), command);
}


Can't wait for process substitution redirected for a subshell

2018-04-24 Thread Geir Hauge
Waiting on a process substitution that is used in redirection for a
command grouping works, but not when using a subshell in place of that
command grouping:

$ TIMEFORMAT=%R
$ time bash -c '{ :; } 2> >(sleep 2); wait "$!"'
2.013
$ time bash -c '(:) 2> >(sleep 2); wait "$!"'
bash: line 0: wait: `': not a pid or valid job spec
0.008

I'd expect those two cases to behave the same way.

It looks like the redirection is done after the subshell is forked, so
adding the wait inside the subshell actually works:

$ time bash -c '(echo "subshell \$! = $!"; wait "$!") 2> >(echo "procsub 
pid = $BASHPID"; sleep 2)'
subshell $! = 74756
procsub pid = 74756
2.014

I get the same behavior with both 4.4.19 and the latest devel snapshot

-- 
Geir Hauge



Re: ~/.profile and ~/.bash_profile aren't executed on login

2017-12-10 Thread Geir Hauge
On Sun, Dec 10, 2017 at 07:22:36PM -0800, Yuri wrote:
> It only calls ~/.profile when it is named 'sh'.

In posix mode, bash only looks for ~/.profile, but when you run it in
non-posix mode, it will look for ~/.bash_profile and ~/.bash_login
first. You probably have a ~/.bash_profile in addition to ~/.profile.

Assuming this is the case, I suggest you merge whatever it contains into
~/.profile, and remove the ~/.bash_profile file.

-- 
Geir Hauge



Re: Trailing newlines disappear

2017-06-08 Thread Geir Hauge
On Fri, Jun 09, 2017 at 03:34:39AM +0700, PePa wrote:
> On 09/06/2560 02:14, Greg Wooledge wrote:
> > Well, it leaves IFS changed, because you didn't revert or unset it,
> > or run the entire thing in a function with local IFS.  Also, I'd use
> > "${MAPFILE[*]}" to reinforce that you are joining an array into a string,
> > rather than expanding the array as a list.
> 
> Thanks for pointing all this out. I settled on:
> mapfile <"$file"; IFS= foo=${MAPFILE[*]} true

Greg already pointed out that this doesn't work.

You can pick one of these instead:

mapfile < "$file"; IFS= foo="${MAPFILE[*]}"; unset -v IFS

or

mapfile < "$file"; printf -v foo %s "${MAPFILE[@]}"

-- 
Geir Hauge



Re: -eq and strings

2017-03-06 Thread Geir Hauge
On Mon, Mar 06, 2017 at 03:31:31PM +0100, Rob la Lau wrote:
> On 06-03-17 15:16, Reuti wrote:
> > if ! expr "$x" : '[[:digit:]]*$' >/dev/null; then echo no; fi
> > 
> > if [ -n "${x//[0-9]/}" ]; then echo no; fi
> 
> True, but regular expressions are usually considered expensive.
> (Must admit I never benchmarked.)
> 
> And I know 1 regex won't considerably slow down my script, but it's
> become a habit to always try and program as light as possible.

If you're counting milliseconds, pattern matching should be slightly
faster than your -eq hack.

is_digit() { [[ -n $1 && $1 != *[![:digit:]]* ]]; }

or the sh variant:

is_digit() { case $1 in ''|*[![:digit:]]*) return 1;; esac; }


See also http://mywiki.wooledge.org/BashFAQ/054

-- 
Geir Hauge



Re: bash "while do echo" can't function correctly

2016-04-13 Thread Geir Hauge
On Wed, Apr 13, 2016 at 10:01:23AM +0800, 何建军 wrote:
> Hi, I use a very simple statement "cat test.txt | while read line; do echo 
> $line; done",  test.txt is very small, no more than 100 lines. but the 
> execution of the statement  paused during process. test.txt is pasted on 
> http://paste.bradleygill.com/index.php?paste_id=1647399 
> desmond.he@xgimi-dev:/studio/desmond.he$ help | head -n 1 GNU bash, version 
> 4.3.11(1)-release (x86_64-pc-linux-gnu) 
> desmond.he@xgimi-dev:/studio/desmond.he$ cat /etc/lsb-release 
> DISTRIB_ID=Ubuntu DISTRIB_RELEASE=14.04 DISTRIB_CODENAME=trusty 
> DISTRIB_DESCRIPTION="Ubuntu 14.04.3 LTS" Thanks for help~

You didn't quote the expansion of the line variable, so the result of
the expansion is first split into words based on the characters in the
special IFS variable, then each of those words that contain glob
characters (like *, ? , [...]) will be replaced by matching filenames,
if any.

It's the last part that bites you here, since several of your lines
contain * characters. Worse if globstar is enabled, since there's also
** in there, so the "pause" you get is probably bash trying to recurse
through the entire filesystem, which may take a while.

The fix is easy. Just surround the expansion in double quotes, which
prevent word-splitting and pathname expansion.

while read -r line; do echo "$line"; done < test.txt

though printf should be preferred over echo:

    while read -r line; do printf '%s\n' "$line"; done < test.txt

-- 
Geir Hauge



read -a ignores upper- and lowercase flags

2016-04-08 Thread Geir Hauge
Configuration Information [Automatically generated, do not change]:
Machine: x86_64
OS: darwin14.5.0
Compiler: /usr/bin/clang
Compilation CFLAGS:  -DPROGRAM='bash' -DCONF_HOSTTYPE='x86_64' 
-DCONF_OSTYPE='darwin14.5.0' -DCONF_MACHTYPE='x86_64-apple-darwin14.5.0' 
-DCONF_VENDOR='apple' -DLOCALEDIR='/opt/local/share/locale' -DPACKAGE='bash' 
-DSHELL -DHAVE_CONFIG_H -DMACOSX   -I.  -I. -I./include -I./lib  
-I/opt/local/include -pipe -Os -DSSH_SOURCE_BASHRC -arch x86_64
uname output: Darwin MacGeir 14.5.0 Darwin Kernel Version 14.5.0: Tue Sep  1 
21:23:09 PDT 2015; root:xnu-2782.50.1~1/RELEASE_X86_64 x86_64
Machine Type: x86_64-apple-darwin14.5.0

Bash Version: 4.3
Patch Level: 42
Release Status: release

Description:

read -ra var  doesn't change the casing of the strings it assigns
when var has been declared with -l or -u.

read without -a, and mapfile both work as expected.

I also tested the latest devel branch to confirm the bug is still
present there.

Repeat-By:

declare -l a b c d
a=( HEllO woRLd )
read -r b <<< "HEllO woRLd"
read -ra c <<< "HEllO woRLd"
mapfile d <<< "HEllO woRLd"
declare -p a b c d

Output:

declare -al a=([0]="hello" [1]="world")
declare -l b="hello world"
declare -al c=([0]="HEllO" [1]="woRLd")
declare -al d=([0]=$'hello world\n')

-- 
Geir Hauge



Re: trap DEBUG and $_

2015-10-12 Thread Geir Hauge
On Mon, Oct 12, 2015 at 07:24:00AM +0200, isabella parakiss wrote:
> On 10/11/15, Dan Stromberg <dstrombergli...@gmail.com> wrote:
> > Is there a way of outputting a datestamp to shell stderr at the _beginning_
> > of the execution of a command, that won't wipe out $_?
> >
> > I use $_ quite a bit for the last argument to the previous command,
> > interactively.  And I'd like to datestamp all my commands. Datestamping
> > after with $PS1 is easy, but datestamping before is a little harder.
> >
> > I've tried using:
> >
> >function preexec { if tty -s; then echo "$(tput smso)cmd started $(date
> > +%Y\ %a\ %b\ %d\ %r)$(tput rmso)"; fi; }
> >trap preexec DEBUG
> >
> > ...but as you might suspect, I'm finding that $_ is always "preexec" with
> > this enabled.
> >
> > Any suggestions?
> >
> > Thanks!
> >
> trap '__=$_; preexec; : "$__"' DEBUG

And since the preexec function ignores its arguments, it can be
shortened to:

trap 'preexec "$_"' DEBUG

-- 
Geir Hauge



Re: bash displays strange characters after base64 decoding

2015-08-07 Thread Geir Hauge
On Thu, Aug 06, 2015 at 07:45:53PM +0200, Valentin Schmidt wrote:
 Bash displays strange characters (including command prompt) (see attached
 png file) after the execution of the base64 (GNU coreutils 8.21) command
 like described as follows:
 base64 -d base64.txt

Xterm has some escape sequences that switch between a second character
set, where many of the ascii letters become line drawing characters
instead. 

Try the following:

printf %b '\e(0' {a..z} '\n' '\e(B' {a..z} '\n'

This prints the 26 lowercase ascii letters in the second character set,
entered by the sequence ESC ( 0, followed by the same line after
switching back, with the sequence ESC ( B. In a Gnome Terminal on Ubuntu
I get the following output from the above:

▒␉␌␍␊°±␤␋┘┐┌└┼⎺⎻─⎼⎽├┤┴┬│≤≥
abcdefghijklmnopqrstuvwxyz

Sven Mascheck has written a bit about this fun feature here:
http://www.in-ulm.de/~mascheck/various/alternate_charset/

-- 
Geir Hauge



Re: substitution read all from fd silently fails: $(0)

2015-07-01 Thread Geir Hauge
On Wed, Jul 01, 2015 at 10:19:10PM +0300, Ilya Basin wrote:
 Hi list.
 
 Want to read whole stdin into variable.
 Don't want to spawn new processes (cat).
 Don't want to reopen existing fd 0
 
 First thing I tried: $(0)
 It silently returns an empty string.

This type of query is preferably asked at the help-bash list rather than
bug-bash.

 
 # works, but too complex
 [root@okdistr ~]# echo aaa | sudo -u nobody bash -c 'a=; while true; do 
 rc=0; read -N1024 b || rc=$?; a=$a$b; [ $rc = 0 ] || break; done; echo $a'
 aaa

IFS= read -rd '' a
printf %s $a



Re: unset does not act as expected on namerefs

2015-05-26 Thread Geir Hauge
On Tue, May 26, 2015 at 11:24:57AM -0400, Shawn Wilson wrote:
 On +2015/05/26 11:04:38, Greg Wooledge wrote:
  On Tue, May 26, 2015 at 10:31:34AM -0400, Shawn Wilson wrote:
   swilson@swlap1:~/temp$ bash --version
   GNU bash, version 4.3.11(1)-release (x86_64-pc-linux-gnu)
   swilson@swlap1:~/temp$ cat t.txt 
   $ome text !n a file|
   swilson@swlap1:~/temp$ unset t
   swilson@swlap1:~/temp$ t=$( ./t.txt)
   swilson@swlap1:~/temp$ echo $t
   bash: $ome text !n a file|: invalid variable name for name reference
   swilson@swlap1:~/temp$ var=foo; declare -n t; t=var; unset t; echo $t
   bash: $ome text !n a file|: invalid variable name for name reference
  
  As surprising as that is, have a look at help unset:
  
 
 So current behavior should stand? I would think that unset (with no
 options) should DWIM. This behavior also seemed to surprise most on
 #bash IRC. This is not a bug for lack of documentation or not
 understanding the results after looking at the doc, but a wow, this
 is surprising - maybe this could behave in a manner so it's not so
 surprising.

The surprising part is that it keeps the -n flag, but partially loses
the nameref ability:

$ var=foo; declare -n ref
$ ref=var
$ printf '%s - ' $ref; declare -p ref
foo - declare -n ref=var
$ unset ref
$ ref=var
$ printf '%s - ' $ref; declare -p ref
var - declare -n ref=var
$ ref=baz
baz - declare -n ref=var

-- 
Geir Hauge



Re: unset does not act as expected on namerefs

2015-05-26 Thread Geir Hauge
On Tue, May 26, 2015 at 11:00:45AM -0500, Eduardo A. Bustamante López wrote:
 # Here we 'unset ref', which actually unsets 'var'. Then, we assign 'var' to
 # 'ref', but since 'ref' is still a nameref, it instead assigns 'var' to 
 'var'.
 dualbus@hp:~$ unset ref; ref=var; echo $ref; declare -p ref
 var
 declare -n ref=var
 dualbus@hp:~$ declare -p var
 declare -- var=var

Ah, that explains it! Mystery solved, and no longer surprising behavior.

-- 
Geir Hauge



mapfile segfaults when unsetting array in callback

2015-03-25 Thread Geir Hauge
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/local/share/locale' -DPACKAGE='bash' 
-DSHELL -DHAVE_CONFIG_H   -I.  -I. -I./include -I./lib   -g -O2
uname output: Linux shbot 3.13.0-44-generic #73-Ubuntu SMP Tue Dec 16 00:22:43 
UTC 2014 x86_64 x86_64 x86_64 GNU/Linux
Machine Type: x86_64-unknown-linux-gnu

Bash Version: 4.3
Patch Level: 33
Release Status: release

Description:
When using mapfile's callback feature, and the callback unsets the
array mapfile is appending to, it segfaults.

Repeat-By:
callback() { unset MAPFILE; }
(mapfile -c 1 -C callback  x)

-- 
Geir Hauge



Re: Does [ -f FILE ] have a bug on testing a symlink ?

2015-02-09 Thread Geir Hauge
2015-02-09 22:00 GMT+01:00 Cheng Rk crq...@ymail.com:

 According this documentation `help test`, I am expecting it should return
 false on anything other than a regular file,

 -f FILETrue if file exists and is a regular file.


 but why it returned true on a symlink to a regular file?

 $ [ -f tmp/sym-link ]  echo true
 true


The manual has this in addition:

«Unless otherwise specified, primaries that operate on files follow
symbolic links and operate on the target of the link, rather than the link
itself.»

http://www.gnu.org/software/bash/manual/bashref.html#Bash-Conditional-Expressions

Probably wouldn't hurt to include that in the help text for the test
builtin as well.

-- 
Geir Hauge


Re: BASH_FUNC__ appearing in environment

2014-11-28 Thread Geir Hauge
2014-11-28 9:43 GMT+01:00 steveT stevetuckn...@yahoo.co.uk:

 OK - found the functions that are appearing. I was grepping BASH_FUNC__ in
 etc - wrong. The functions are in the /usr/share/bash-completion/completions
 directory - and exist as rcs and sudo  files. The code in those files
 defines functions for _rcs and _sudo respectively. The rcs file contains:

 # bash completion for rcs  -*-
 shell-script -*-

 _rcs()
 {
  [--snipp--]
 } 
 complete -F _rcs ci co rlog rcs rcsdiff

 # ex: ts=4 sw=4 et filetype=sh

 OK - so that is the code that appears in my environment as BASH_FUNC__rcs
 - now the question is - why - and why does it persist? I am not aware of
 using completion with sudo or rcs - so where/why/how in bash do these
 /usr/share scripts get actioned?


The third-party bash-completion package sets a default completion
function (see it with complete -p -D; declare -f _completion_loader) that
dynamically loads completions. For instance, if you do

$ rcs TAB

And there is not already a completion loaded for rcs, It will look for
/usr/share/bash-completion/completions/rcs, source it if it finds it, then
use the new completion. This in itself will not cause the function to be
exported. I can only think of two ways of the function being exported, and
that's by

1. specifically exporting it with ''export -f _rcs'' or ''declare -xf _rcs''
2. you happen to run ''set -a'' at some point before the completion
function gets dynamically loaded. When ''set -a'' is in effect, all
variables and functions you define get automatically exported. If the
output of ''echo $-'' contains 'a', then it is in effect.

-- 
Geir Hauge


Re: feature: time builtin and file descriptor

2014-10-31 Thread Geir Hauge
2014-10-29 15:09 GMT+01:00 Sami Kerola kerol...@iki.fi:

 This idea came to my mind while writing a script that runs multiple
 commands, and I simply wanted to know how long they are busy.  I am
 aware alternatives exist, but they can get a bit tricky if one wants to
 have multiple measurements going on simultaneously.  For example:

 exec 420
 time --file-descriptor 42
 for i in items; in
 exec 520
 time --file-descriptor 52
 echo processing $i
 [...]
 echo item $i took
 exec 52-
 done
 echo 'all together took:'
 exec 42-


You could achieve this by using command grouping and TIMEFORMAT:

items=( a b c )
time {
for i in ${items[@]}; do
time {
echo processing $i
sleep $((RANDOM%5 + 1))
TIMEFORMAT=item $i took %R seconds
}
done
TIMEFORMAT='all together took: %R seconds'
}

example output:

processing a
item a took 5.001 seconds
processing b
item b took 1.001 seconds
processing c
item c took 3.001 seconds
all together took: 9.004 seconds


It would be prettier if TIMEFORMAT could be set on invocation of time,
e.g.  TIMEFORMAT='foo took %R seconds' time { ...; } , but time being a
keyword probably makes that hard.

One also has to be careful to sanitize any variables one embeds in
TIMEFORMAT since % characters are special.

-- 
Geir Hauge


Re: Issues with exported functions

2014-09-25 Thread Geir Hauge
2014-09-25 6:23 GMT+02:00 Linda Walsh b...@tlinx.org:

 Maybe exporting fun?

   export fun='() { :;}'
  bash -c 'declare -pf fun'

 bash: line 0: declare: fun: not found
 ...
 I've never seen functions created with an assignment.  Is this a
 new syntax in 4.3?

 (still in 4.2.43 here)...


Bash has had this feature since forever

$ fun='() { echo $BASH_VERSION;}' bash1 -c fun
1.14.7(1)

Your bash 4.2.43 is no exception, but the way declare's -p and -f
options interact did change in 4.3, so try with just ''declare -f fun''
instead

-- 
Geir Hauge


Re: Issues with exported functions

2014-09-25 Thread Geir Hauge
2014-09-25 10:43 GMT+02:00 Davide Brini dave...@gmx.com:

 I'm not arguing about anything, I just have a question. I understand that
 with the current method used to export functions, it is not possible to
 export a variable to a child whose value begins exactly with the characters
 in question. A quick test seems to confirm that:

 $ x='() { echo a; }' bash -c 'echo $x'

 $ x='()  { echo a; }' bash -c 'echo $x'
 ()  { echo a; }


 So is there a way to be able to export variables with arbitrary values,
 including '() {' ?  Sorry if this has been discussed before.


There's the -p flag, but it has other side effects

$ x='() { echo a; }' bash -pc 'echo $x'
() { echo a; }

I also dislike that it parses exported functions by default; it violates
the don't treat data as code rule. Sure would be nice if there was a
separate flag that only disables parsing of exported functions.

-- 
Geir Hauge


Re: Segmentation fault bash 4.3.022

2014-08-11 Thread Geir Hauge
2014-08-11 20:47 GMT+02:00 Greg Wooledge wool...@eeg.ccf.org:

 On Tue, Aug 12, 2014 at 02:21:18AM +0800, lolilolicon wrote:
  The following code segfaults when run by bash 4.3.022
 
set -E
shopt -s lastpipe
trap -- 'true' ERR
true | { true | false; }

 I could not reproduce this, on HP-UX or Linux.  I tried from an
 interactive shell, just typing these commands.  Did you use a script?
 Is your bash 4.3.22 from an OS distribution package, or did you compile
 it yourself?  If it's a script, is BASH_ENV set?  Can you still trigger
 the bug with an interactive shell, or with an interactive shell started
 with --norc?


I can reproduce this on linux for non-interactive bash (which makes
sense since lastpipe doesn't do much when set -m is in effect), but it's
not limited to 4.3.22, and set -E does not appear to affect the outcome.

$ bash42 -c 'echo $BASH_VERSION;shopt -s lastpipe; trap -- printf x
ERR; true | { true | false; }'
4.2.47(2)-release
xxSegmentation fault

$ bash43 -c 'shopt -s lastpipe; trap -- printf x ERR; true | { true |
false; }'
4.3.22(1)-release
xxSegmentation fault

And lastly, in interactive mode
$ set +m; shopt -s lastpipe; trap -- printf x ERR; true | { true | false;
}
xxx

Can't quite understand why it would trigger the ERR trap thrice.

-- 
Geir Hauge


Re: sourcing script file from inside a function doesn't work anymore

2014-05-12 Thread Geir Hauge
2014-05-12 14:11 GMT+02:00 Greg Wooledge wool...@eeg.ccf.org:

 On Sat, May 10, 2014 at 12:22:40PM +0200, thioroup8 wrote:
  Now, I source it from inside a function: I obtain following error
 message:
  bash: declare: tmp: not found
  I think this problem raises in the particular case of involving array
  variables definitions inside sourced bash script file...

cat  EOF  ${file_to_be_sourced}
  declare -a tmp='([0]=1 [1]=2)'
  EOF

 The problem is that you are using declare within the file-to-be-sourced.
 When you source the file inside a function, Bash runs the declare command
 within the context of the function, where declare has the same meaning as
 local.  Thus, it makes the variable local to the function.


There really is a bug here, a weird one. Using a simplified script, we
see that this works as expected:

$ source (printf declare -a array='(x)'; declare -p array\n)
declare -a array='([0]=x)'


Wrapping it in a function should yield the same output, but doesn't:

$ f() { source (printf declare -a array='(x)'; declare -p array\n); }; f
bash: declare: array: not found


And while declare -p array fails to find the array, declare -p
(without a name) does list it:

$ f() { source (printf declare -a array='(x)'; declare -p array; declare
-p | grep array= \n); }; f
bash: declare: array: not found
declare -a array='([0]=x)'


Oddly, the quotes seem to matter; changing array='(x)' to array=(x)
makes it work...

$ f() { source (printf declare -a array=(x); declare -p array\n); }; f
declare -a array='([0]=x)'

-- 
Geir Hauge


Re: ${assoc[key]+set} no longer works.

2014-03-19 Thread Geir Hauge
2014-03-18 16:19 GMT+01:00 Chet Ramey chet.ra...@case.edu:

 On 3/18/14 5:36 AM, geir.ha...@gmail.com wrote:

  Bash Version: 4.3
  Patch Level: 0
  Release Status: release
 
  Description:
  With an associative array, assoc, ${assoc[key]+set} expands to the
  empty string if the associated value is the empty string.

 Thanks for the report.  This was a consequence of a change made back in
 2011 to expand the value portion of the assignment statement a slightly
 different way.  I've attached a patch to fix it.


Thanks. That patch also makes  [[ -v assoc[x] ]]  return 0. However,
[[ -v assoc ]] returns 1 (which it also does before the patch). Sounds
related to this bug.

-- 
Geir Hauge


${assoc[key]+set} no longer works.

2014-03-18 Thread geir . hauge
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/local/share/locale' -DPACKAGE='bash' 
-DSHELL -DHAVE_CONFIG_H   -I.  -I. -I./include -I./lib   -g -O2
uname output: Linux gina 3.2.0-59-generic #90-Ubuntu SMP Tue Jan 7 22:43:51 UTC 
2014 x86_64 x86_64 x86_64 GNU/Linux
Machine Type: x86_64-unknown-linux-gnu

Bash Version: 4.3
Patch Level: 0
Release Status: release

Description:
With an associative array, assoc, ${assoc[key]+set} expands to the
empty string if the associated value is the empty string.

Repeat-By:
$ declare -A assoc='([x]= [y]=1 )'
$ printf '%s\n' ${assoc[x]+x is a key} ${assoc[y]+y is a key}

y is a key




Re: The default value of TIMEFORMAT is incorrectly formatted

2013-11-02 Thread Geir Hauge
2013/11/2 Chet Ramey chet.ra...@case.edu

 On 11/1/13, 5:54 PM, Seungbeom Kim wrote:
  Description:
The default value of TIMEFORMAT is incorrectly formatted:
it is shown as   $'\nreal\t%3lR\nuser\t%3lU\nsys%3lS' in the man
 page,
but it should be $'\nreal\t%3lR\nuser\t%3lU\nsys\t%3lS'.

 Thanks for the report.  This has already been fixed for bash-4.3.


I reported this a while back too, and it is changed in the latest devel
branch, but it appears you introduced a different typo:

$'\nreal\t%3lR\nuser\t%3lU\nsys\tt%3lS'

-- 
Geir Hauge


Re: operator prevents backgrounding over ssh

2013-09-26 Thread Geir Hauge
2013/9/26 Hinrik Örn Sigurðsson hinrik@gmail.com

 The  operator in bash seems to inhibit backgrounding when run over
 ssh. You can try it with the following:

   ssh localhost cd /tmp  nohup sleep 10 /dev/null 21 

 The above command will wait for sleep(1) to finish before returning.
 If it is run without ssh, it returns immediately. Furthermore, other
 shells such as dash and zsh will return immediately regardless of
 whether ssh is used.


Probably because it's equivalent to

  { cd /tmp  nohup sleep 10 /dev/null 21; } 

so the backgrounded process still have stdout and stderr connected to ssh.
This should do what you want:

  cd /tmp  { nohup sleep 10 /dev/null 22  }

-- 
Geir Hauge


Re: Inaccurate modification date testing

2013-08-14 Thread Geir Hauge
2013/8/14 Jacek Krüger jacek.kru...@gmail.com

 Bash is innacurate when testing modification dates. It ignores fractions
 of a second. Is it expected? Coreutils test does it properly.


Looks like that is fixed in 4.3-alpha

http://git.savannah.gnu.org/cgit/bash.git/tree/CHANGES?h=devel#n554

-- 
Geir Hauge


Invalid extglob causes segfault with help builtin.

2013-08-05 Thread Geir Hauge
Configuration Information [Automatically generated, do not change]:
Machine: i686
OS: linux-gnu
Compiler: gcc
Compilation CFLAGS:  -DPROGRAM='bash' -DCONF_HOSTTYPE='i686'
-DCONF_OSTYPE='linux-gnu' -DCONF_MACHTYPE='i686-pc-linux-gnu'
-DCONF_VENDOR='pc' -DLOCALEDIR='/usr/local/share/locale' -DPACKAGE='bash'
-DSHELL -DHAVE_CONFIG_H   -I.  -I. -I./include -I./lib   -g -O2
uname output: Linux sikozu 3.2.0-40-generic #64-Ubuntu SMP Mon Mar 25
21:22:26 UTC 2013 i686 i686 i386 GNU/Linux
Machine Type: i686-pc-linux-gnu

Bash Version: 4.2
Patch Level: 45
Release Status: release

Description:
One of the side-effects of the latest changes of the help
builtin in the devel release is that ''help (('' no longer
shows the help for (( ... )), so I casually threw some asterisks
around it ... and got a segfault. This also happens in bash
4.2.45 and 4.2.25, but not 3.2.48. It only segfaults when
extglob is enabled; probably because it's an incomplete extglob.

Repeat-By:
bash -O extglob -c 'help *((*'

-- 
Geir Hauge


Re: PS1 multiline with colors

2013-07-09 Thread Geir Hauge
2013/7/9 Dan Douglas orm...@gmail.com

 Can also give all the debug output %q formatting.

 exec {BASH_XTRACEFD} (set +x; while IFS= read -r x; do printf %q\\n
 $x; done)


Note that {BASH_XTRACEFD}... won't work in bash 4.2 (or older). It's fixed
for the next release though.

http://lists.gnu.org/archive/html/bug-bash/2012-09/msg6.html

-- 
Geir Hauge


Re: Redirect a backgrounded process' stdout toward COPROC's stdin

2012-06-03 Thread Geir Hauge
2012/6/3 Davide Baldini baldiniebald...@gmail.com:
 Description:
 In the following test script I run an elementary coprocess to which the
 echo built-in, run in background, attaches its standard-output:

    #!/bin/bash
    # TEST 1
    coproc /bin/sleep 100
    echo ${COPROC[1]} 

 The script always fails, for no apparent reason, giving the output:

    ./test.sh: line 4: ${COPROC[1]}: Bad file descriptor

The coproc fds are only available in the same shell. The subshell
created with  cannot use them.


 I wonder if the correct syntax should be rather this one (ampersand
 moved before redirection):

    #!/bin/bash
    # TEST 2
    coproc /bin/sleep 100
    echo  ${COPROC[1]}

This is equivalent to

echo 
${COPROC[1]}

 ends the command, so the redirection is not applied to the echo.


See http://wiki.bash-hackers.org/syntax/keywords/coproc

-- 
Geir Hauge



Re: handling of test == by BASH's POSIX mode

2012-05-27 Thread Geir Hauge
2012/5/27 Jon Seymour jon.seym...@gmail.com:
 Is there a reason why bash doesn't treat == as an illegal test
 operator when running in POSIX mode?

POSIX does not say == is not allowed.

POSIX tells you what the shell should at least be able to do. A POSIX
compliant shell can have whatever other features it likes, as long as
the POSIX features are covered.


 This is problematic because use of test == in scripts that should be
 POSIX isn't getting caught when I run them under bash's POSIX mode.
 The scripts then fail when run under dash which seems to be stricter
 about this.

Don't use non-POSIX features in a POSIX script, and you'll be fine.
http://www.opengroup.org/onlinepubs/9699919799/utilities/contents.html

-- 
Geir Hauge



Re: compgen is slow for large numbers of options

2012-03-19 Thread Geir Hauge
2012/3/19 Chet Ramey chet.ra...@case.edu:
 I will look at optimizing that function, but it's always going to take time
 to plow through 300K when you have to split it into words.  (There's not
 actually any word splitting of consequence happening with your second
 example using the pipeline.)

Letting compgen do the command substitution speeds it up considerably

$ TIMEFORMAT=%R
$ time compgen -W `seq 1 50` 1794 /dev/null
175.253
$ time compgen -W '`seq 1 50`' 1794 /dev/null
2.347

-- 
Geir Hauge



Re: TAB vs. colon

2011-12-30 Thread Geir Hauge
2011/12/30 jida...@jidanni.org

 But sometime we don't type in the path by hand, but instead paste it in
 from elsewhere via the mouse or something. In this case we have to
 painfully add the \   \ stuff by hand before any TAB expansion works.


A workaround would be to quote the path. E.g. instead of

ls pasteutab

do

ls 'paste'utab

-- 
Geir Hauge


Re: ';' redirection operator [was: [1003.1(2008)/Issue 7 0000530]: Support in-place editing in sed (-iEXTENSION)]

2011-12-22 Thread Geir Hauge
2011/12/22 Bruce Korb bk...@gnu.org

 When the exact opposite is the useful variation?  I.e. keep-on-failure.
 -i for sed is simple, understandable and implemented a lot.


As far as I know, -i is only implemented with GNU sed and BSD sed, and they
are incompatible, BSD sed's -i takes a mandatory argument, while GNU sed's
-i takes an optional string which must be provided in the same argument.
E.g.

gnused -i.bak sed-script file
bsdsed -i .bak sed-script file

So the only portable way of using sed to edit (read: overwrite) a file is
with

sed sed-script file  file.tmp  mv file.tmp file

I'd welcome this ; syntax.

-- 
Geir Hauge


Re: exit status issue

2011-11-18 Thread Geir Hauge
2011/11/17 Dallas Clement dallas.a.clem...@gmail.com


  Would appreciate any insight you could offer.  Here is my script and
 the strace output for when touch returns 1.


Add ''set -x'' at the start of the function and examine the output to see
if it actually runs touch from PATH.

-- 
Geir Hauge


Re: invoke tilde expansion on quoted string

2011-11-12 Thread Geir Hauge
2011/11/12 Chris F.A. Johnson ch...@cfajohnson.com

 On Fri, 11 Nov 2011, Peng Yu wrote:

 I'm wondering if I already have a string variable, is there a bash
 native to do tilde expansion on it.

 var='~/..'
 cd $var#how to change this line?


  eval cd $var


I'd avoid eval as that could potentially do more than just expand the
tilde, depending on what other characters the var contains. I'd just
replace the ~ with $HOME using parameter expansion.

cd ${var/#~\//$HOME/}

-- 
Geir Hauge


Re: bug? {1..3} doesnt' use IFS to separate fields

2011-07-27 Thread Geir Hauge
2011/7/25 Linda Walsh b...@tlinx.org



 I know it wasn't designed this way, but it seems like it
 is a bug.


The manual says nothing about brace expansion using IFS in any way, so it's
not a bug.


If I do
  read a b c $(echo {1..3} ); echo a:$a b:$b c:$c
 I get:
  a:1 b:2 c:3

 But If I do
  export IFS=','; read a b c $(echo {1..3} ); echo a:$a b:$b c:$c
 I get:
  a:1 2 3 b: c:

 Why should the 2nd case return the wrong answer?
 I.e. shouldn't {1..3} use the IFS to separate arguments?


I don't see the usefulness in having brace expansion's behavior changed by
IFS.

If you want {1..3} to turn into the string 1;2;3, assign it to an array,
then print the array that way

array=( {1..3} )
(IFS=';'; echo ${array[*]}) # outputs 1;2;3
printf -v var '%s;' ${array[@]}; echo $var # outputs 1;2;3;

-- 
Geir Hauge