Re: [Parameter Expansion] bug in ${variable% *}
On 12.02.2013 18:50, Dashing wrote: On Tue, 12 Feb 2013 18:02:05 +0100 "Chet Ramey" I've fixed the problem, and the fix will be in the next release. Thank you, Chet! On Tue, 12 Feb 2013 10:13:46 +0100 "Bernd Eggink" superfluous blank in the ${rest: -1} expression Bernd, this blank makes a big difference: ${rest: -1} last character of $rest ${rest:-1} $rest or 1 if $rest is empty You're right, of course. Sigh. Fortunately I've not yet fallen into that pithole... Bernd -- www.sudrala.de
Re: [Parameter Expansion] bug in ${variable% *}
On 11.02.2013 18:50, Dashing wrote: Bash version: 4.2.042 I have a script that behaves erratically: = #! /bin/bash last=${1##* } rest=${1% *} while [[ "${rest: -1}" == '\' ]]; do last="${rest##* } $last" oldrest=$rest rest=${rest% *} if [[ "$oldrest" == "$rest" ]]; then echo :--Mistake--: # sleep 0.01 # rest=${rest% *} # if [[ "$oldrest" == "$rest" ]]; then # echo 'unable to interpret' # break # fi fi done echo REST:$rest: echo LAST:$last: = $ ./pe 'mplayer foo1\ foo2\ foo3\ 4\ 5\ foo6\ 7' :--Mistake--: :--Mistake--: REST:mplayer: LAST:foo1\ foo1\ foo1\ foo2\ foo3\ 4\ 5\ foo6\ 7: = What happens is that rest=${rest% *} doesn't always update $rest, even when there are spaces left in $rest. Meanwhile last="${rest##* } $last" works every time. In the above example it got stuck twice when $rest was mplayer foo1\. It tends to vary wildly. The script runs fine if you omit the superfluous blank in the ${rest: -1} expression: while [[ "${rest:-1}" == '\' ]]; do If the script behaves indeterministic, it is probably a bash bug. Regards, Bernd -- www.sudrala.de
Re: equivalent of Linux readlink -f in pure bash?
On 09.08.2011 16:54, Stephane CHAZELAS wrote: 2011-08-09, 09:50(-04), Steven W. Orr: [...] *) To remove the trailing slashes, instead of while [[ $file == */ ]] do file=${file%/} done file=${file##*/}# file name just say file="${file%${file##*[!/]}}" [...] file=${file%"${file##*[!/]}"} Same problem with "/" being changed to "" though. This has been fixed. Also getlink() now outputs paths always in normalized form. Any feedback appreciated! Bernd -- http://sudrala.de
Re: equivalent of Linux readlink -f in pure bash?
On 09.08.2011 15:50, Steven W. Orr wrote: On 8/9/2011 5:29 AM, Bernd Eggink wrote: On 09.08.2011 03:44, Jon Seymour wrote: Has anyone ever come across an equivalent to Linux's readlink -f that is implemented purely in bash? You can find my version here: http://sudrala.de/en_d/shell-getlink.html As it contains some corrections from Greg Wooledge, it should handle even pathological situations. ;) Bernd I'd just like to make a couple of suggestions for your script (I hope these are welcome): You are welcome! *) You reset OPTIND to 1 but you didn't declare it local. This will cause any caller of getlink which uses getopts to reset its variable to 1. (I mention this because it cost me a couple of hours a while back.) The reason I didn't declare OPTIND local is that OPTIND is handled specially by the shell; there is always exactly _one_ instance of this variable. In other words, OPTIND is always global, even if declared local (which is indeed pretty weird). Try this: --- function f { local OPTIND=1 echo "\$1=$1" } while getopts "abcdefg" opt do echo "opt=$opt" f $opt done Calling the sript like this works fine: script -a -b -c But calling it like this leads to an endless loop: script -abc One could of course save and restore the original: --- function f { local oldind=$OPTIND OPTIND=1 echo "\$1=$1" OPTIND=$oldind } --- However, this also loops endlessly. The reason is most likely that bash maintains an additional internal variable holding the index of the current character, relative to the current word. While this variable is not directly accessible by the user, it is set to 0 whenever OPTIND is assigned a value. So the only safe way is to _never_ use getopts within another getopts block, but always wait until the first one has finished. When calling getopts, especially from a function that is intended to not be used at a top level for processing command line options, you should declare local copies of OPTIND, OPTARG and OPTERR. *) To remove the trailing slashes, instead of while [[ $file == */ ]] do file=${file%/} done file=${file##*/} # file name just say file="${file%${file##*[!/]}}" Yes, you can do that, but I find my version a bit more legible. Also, for file=/ it returns a single slash, while yours returns an empty string. (Hmm... the next statement in my script also creates an empty string, but this is a bug and will be fixed). *) Instead of [[ ! -d $dir ]] && { ret=1 break } how about this for slightly cleaner? [[ -d $dir ]] || { ret=1 break } I think that's just a matter of taste. Greetings, Bernd -- http://sudrala.de
Re: equivalent of Linux readlink -f in pure bash?
On 09.08.2011 03:44, Jon Seymour wrote: Has anyone ever come across an equivalent to Linux's readlink -f that is implemented purely in bash? You can find my version here: http://sudrala.de/en_d/shell-getlink.html As it contains some corrections from Greg Wooledge, it should handle even pathological situations. ;) Bernd -- http://sudrala.de
Re: Bash-4.2-rc2 available for FTP
Am 02.02.2011 14:56, schrieb Chet Ramey: The second release candidate of bash-4.2 is now available with the URL ftp://ftp.cwru.edu/pub/bash/bash-4.2-rc2.tar.gz Thanks. Unfortunately, this version is incredibly slow. For example, it needs 20 seconds (!) to source the bash_completion file, as opposed to 0.2 seconds with 4.1-9. Counting from 1 to 1 is about 20 times slower. Maybe due to heavy debugging? Regards, Bernd -- Bernd Eggink http://sudrala.de
Re: Issues when func name is the same with an alias
Am 04.08.2010 16:38, schrieb Clark J. Wang: On Wed, Aug 4, 2010 at 8:27 PM, Bernd Eggink wrote: Am 04.08.2010 12:39, schrieb Clark J. Wang: I was testing the precedence between functions and aliases so I tried like this (with bash 4.1.5): $ cat rc alias foo='echo this is the alias' foo() { builtin echo 'this is the function' } foo $ source rc bash: confusing-aliases-2.sh: line 4: syntax error near unexpected token `(' bash: confusing-aliases-2.sh: line 4: `foo()' $ Seems like I must explicitly use the `function' keyword to define foo() for this scenario. Is that the correct behavior? The man page says "The first word of a simple command, if unquoted, is checked to see if has an alias". Therefore 'foo' in your function declaration is replaced by 'echo this is the alias'. Unfortunately, you can't quote the function name in the declaration, so you have to either use 'function' or say "unalias foo" first. Function definitions are not simple commands. Actually, func definition syntax is listed under the *Compound Commands* section in bash2.05b's man page and in bash3+ it's been moved to a separate section. The function *body* as part of the definition is a compound command. The definition as a whole constitutes a simple comand. You can see that function definitions are not listed under "compound commands", but adhere to the definition of simple commands: "A simple command is a sequence of optional variable assignments followed by blank-separated words and redirections, and terminated by a control operator." Some lines above '(' is listed as a control operator. The only questionable term is "...a sequence of optional variable assignments followed by...", as it appears that variable assignments are not allowed before a function definition. I suppose that is just a documentation issue. Can anybody comment on this? Regards, Bernd -- Bernd Eggink http://sudrala.de
Re: Issues when func name is the same with an alias
Am 04.08.2010 15:13, schrieb Eric Blake: On 08/04/2010 05:03 AM, Marc Herbert wrote: Le 04/08/2010 11:39, Clark J. Wang a écrit : Seems like I must explicitly use the `function' keyword to define foo() for this scenario. Is that the correct behavior? The correct behaviour is simply not to use aliases, since they bring nothing to the table compared to functions. Not _quite_ true - there are a few things aliases can do that functions cannot, and when combined, you can get some cool interactive effects (although I don't recommend relying on this in scripts): http://www.chiark.greenend.org.uk/~sgtatham/aliases.html Interesting article. One thing not mentioned there is declarations. alias assoc='declare -A ' assoc x y z Not particularly useful, but you can't replace that with a function (as long as there is no 'global' option for declare). Bernd -- Bernd Eggink http://sudrala.de
Re: Issues when func name is the same with an alias
Am 04.08.2010 12:39, schrieb Clark J. Wang: I was testing the precedence between functions and aliases so I tried like this (with bash 4.1.5): $ cat rc alias foo='echo this is the alias' foo() { builtin echo 'this is the function' } foo $ source rc bash: confusing-aliases-2.sh: line 4: syntax error near unexpected token `(' bash: confusing-aliases-2.sh: line 4: `foo()' $ Seems like I must explicitly use the `function' keyword to define foo() for this scenario. Is that the correct behavior? The man page says "The first word of a simple command, if unquoted, is checked to see if has an alias". Therefore 'foo' in your function declaration is replaced by 'echo this is the alias'. Unfortunately, you can't quote the function name in the declaration, so you have to either use 'function' or say "unalias foo" first. Regards, Bernd -- Bernd Eggink http://sudrala.de
Re: RFE? request for an "undefined" attribute for functions
Am 02.08.2010 20:16, schrieb Eric Blake: On 08/02/2010 12:15 PM, Bernd Eggink wrote: Am 02.08.2010 19:15, schrieb Andreas Schwab: Bernd Eggink writes: eval "function $name Don't use function, use "$name ()" instead. What's wrong with function?? 'function name' is a bash extension while 'name()' is POSIX. If you use standard POSIX instead of bash extensions, then your approach will more easily port to other POSIX shells. It's not just a bash extension. Ksh and zsh also have the 'function' keyword, probably other shells as well. I prefer it in ksh because it makes locally declared variables really local, while with the name() syntax they are shared with the environment. That's one reason why it became a habit. The other is that 'function' is clear and self-explaining, while 'name()' wrongly suggests that function parameters should be surrounded by parentheses. Apart from that, I can't see why I should care for POSIX when writing bash-specific hacks. Regards, Bernd -- Bernd Eggink http://sudrala.de
Re: RFE? request for an "undefined" attribute for functions
Am 02.08.2010 19:15, schrieb Andreas Schwab: Bernd Eggink writes: eval "function $name Don't use function, use "$name ()" instead. What's wrong with function?? Bernd -- Bernd Eggink http://sudrala.de
Re: RFE? request for an "undefined" attribute for functions
Am 02.08.2010 03:10, schrieb Linda Walsh: I had(have) several functions that I don't use on a regular basis (rarely), that I had put into a subdir "func_lib" under my local-definitions directory. This came from ksh, which allows you to define functions with an "undef" attribute, and at runtime, the first time these functions were referenced, Is this something that might have been considered for bash? It seems like it could have some usefulness? If you are concerned about memory usage, you could use a mechanism like this: #- function undef { local name for name do eval "function $name { source $FUNCDIR/$name $name \"\...@\" }" done } #- The call undef f1 f2 f3 (corresponding to 'autoload f1 f2 f3' in ksh) creates small placeholder functions f1, f2, and f3. The first call to any of these functions will replace its definition by the one found in $FUNCDIR, and also call the latter. I'm not sure, however, if this is guaranteed to work in any case (and in any bash version). Greetings, Bernd -- Bernd Eggink http://sudrala.de
Re: weird behaviour of ((count++)) when using , , to change to lower case
Am 01.08.2010 13:06, schrieb Andrew Benton: Also good. Now try converting it to lower case with ,, andy:~$ count=0 andy:~$ echo "${days[${count}],,}, ${days[$((count++))],,}, ${days[$((count++))],,}" monday, tuesday, thursday What happened to wednesday? I'd rather expect this to print "monday, monday, tuesday", since you left out the ++ in the first term. I think the problem is that the ,, operator causes each expression to be evaluated twice. That would explain this behaviour, and it's a bug IMHO. Regards, Bernd -- Bernd Eggink http://sudrala.de
Indirect expansion and arrays
It seems that indirect expansion doesn't work with arrays: $ a=(x y z) $ b=a $ echo "${!b[0]} ${!b[1]} ${!b[2]}" x Is that intended? The documentation isn't explicit about it. IMHO it would be very desirable to have a indirect expansion facility for arrays. Otherwise there is only a choice between passing all elements to a function, which is time-consuming, or using eval, which is cumbersome and error-prone. Regards, Bernd -- Bernd Eggink http://sudrala.de
Re: function grammar
Am 19.07.2010 08:30, schrieb Ken Irving: On Sun, Jul 18, 2010 at 11:53:02AM -0700, Linda Walsh wrote: from man bash, to define a function use; "function" "name" OR "name" () right? And Compound Commands are: () {; ) (( expression )) [[ expression ]] ...et al so why do I get a syntax error for function good_dir [[ -n $1&& -d $1&& -r $1&& -x $1 ]] bash: syntax error near unexpected token `[[' I see this in bash(1): SHELL GRAMMAR ... Shell Function Definitions ... [ function ] name () compound-command [redirection] and do not see the version you show without the parens. It's there. Look at the 3rd sentence: "If the function reserved word is supplied, the parentheses are optional." Bernd -- Bernd Eggink http://sudrala.de
Re: [bash-bug] parsing error with heredoc and command substitution
Am 15.07.2010 10:35, schrieb Andreas Schwab: "Dr. Werner Fink" writes: a=$((/bin/cat|wc -l)< Useless subshell. a=$({ /bin/cat | wc -l; }< ...and useless cat: a=$(wc -l <Nevertheless, IMHO the OP's version should work. It works in ksh, for example. Bernd -- Bernd Eggink http://sudrala.de
Wrong alignment in select lists
Select lists are sometimes displayed with incorrect vertical alignment if an item contains one or more German umlauts. Examples: select x in äöü blah{1..20}; do :; done # wrong select x in amöbe blah{1..20}; do :; done # wrong select x in amöb blah{1..20}; do :; done# wrong select x in amö blah{1..20}; do :; done # OK Bash version is 4.1.7(1)-release, LANG is de_DE.UTF-8. Bernd -- Bernd Eggink http://sudrala.de
Re: create array in loop with variable in array's name
Am 29.05.2010 01:04, schrieb pikta: Hi all, I'm just a beginer and I got stucked I'm trying to create multiple array with variable in array's name. I would expect to have 3 arrays and each of them would contain 3 elements like array1=(a b c) array2=(a b c ) array3=(a b c) ; what means that first element of array1[0]="a" and for example third element of array3[2]="c". This is the way how I do it : for (( n=1; n<4; n++ )) do array$n=(a b c) done ...but there is syntax error That's because array$n isn't a valid name. Use eval: eval "array$n=(a b c)" Bernd -- Bernd Eggink http://sudrala.de
Re: Is there a special variable for the directory where the script is in?
Am 12.02.2010 15:39, schrieb Greg Wooledge: On Fri, Feb 12, 2010 at 02:53:39PM +0100, Bernd Eggink wrote: I once wrote a more generic shell function for this purpose, see: http://sudrala.de/en_d/shell-getlink.html You note that it doesn't handle names containing ->, which is true. I'll get back to that at the end. It also won't handle any name that "ls -l" will refuse to print out correctly on any given system. Also, there are three more cases that it can't handle. The first is due to missing quotes in your command: echo ${link##*-> } Without quotes, this will mangle all leading, trailing or repeated whitespace. Easily fixed by adding the quotes. (There are a few other cases of missing quotes too.) Thanks. I knew there were some missing cases, but when I wrote it, I didn't consider hardening the function against insane filenames worth the effort. However, it now begins to interest me if this is common practice. How big is the probability to stumble upon such filenames is in real life? Bernd -- Bernd Eggink http://sudrala.de
Re: Is there a special variable for the directory where the script is in?
Am 12.02.2010 14:38, schrieb Guillaume Outters: Greg a écrit : Except that HP-UX 10.20 and HP-UX 11.11 don't have readlink(1). (Maybe it's added in 11.2x? I don't know.) You're right. I must admit I made a concession to some GNU coreutils tools on the platform. I once used some ls -l "$SCRIPTS" | sed -e 's/.* -> //' magic to replace it (and it worked two minutes ago on the HP-UX, just like it used to back in the old days). I once wrote a more generic shell function for this purpose, see: http://sudrala.de/en_d/shell-getlink.html Bernd -- Bernd Eggink http://sudrala.de
Re: add a way to declare global variables
Am 12/14/09 13:37, schrieb Marc Herbert: Bernd Eggink a écrit : To avoid misunderstandings, let me add that you are right (only) with respect to variables being used _without_ declaration. OK, but not having to explicitly "declare" variables is a feature that most people expect from dynamic languages, so you can hardly blame them for doing this all the time in shell. I don't blame anybody. I'm talking about the fact that associative arrays are an exception from "what most people expect from dynamic languages", as they _have_ to be explicitly declared. This doesn't bother me, but I would prefer to have a choice between local and global declaration anyway. -- Bernd Eggink http://sudrala.de
Re: add a way to declare global variables
Am 12.12.2009 21:41, schrieb Chet Ramey: On 12/12/09 5:28 AM, Bernd Eggink wrote: Am 10.12.2009 10:40, schrieb konsolebox: I hope the development team will also consider adding a way in bash to declare global variables inside a function perhaps either with an option in typeset or declare like -g (same as zsh) and/or a builtin function like global as similar to local. I second that. I'm missing this feature badly. Presently, you can only get around this restriction by using a lot of ugly and dangerous 'eval's. OK. I'm interested in use cases for this feature. What are you trying to do that you're missing it "badly?" One example is introducing some kind of data encapsulation in bash, or even a modest form of object orientation. You may laugh at it, but I think it might be useful in complex scripts. I experimented a little and came up with 'classes' consisting of a function, and 'objects' consisting of a function (representing the interface) plus an equally named associative array (containing the data). The difficulties arise if you want to create an object 'a' of class X by saying X create a You can declare a function 'a' dynamically within function X (using eval), but you can't declare a (global) associative array 'a' there. So that's where a global declaration would be desirable. The alternative is to print the declarations and eval the whole thing in the current environment, but that is very inconvenient and can cause nasty quoting problems. Regards, Bernd -- Bernd Eggink http://sudrala.de
Re: add a way to declare global variables
Am 12.12.2009 15:25, schrieb DennisW: On Dec 12, 4:24 am, Bernd Eggink wrote: Am 12.12.2009 02:11, schrieb Matthew Woehlke: konsolebox wrote: I hope the development team will also consider adding a way in bash to declare global variables inside a function perhaps either with an option in typeset or declare like -g (same as zsh) and/or a builtin function like global as similar to local. I thought variables in functions were /always/ global unless declared local? It's the other way round. Regarding typeset and declare, the man page says: " When used in a function, makes each name local, as with the local command. " So within a function, typeset, declare, and local are synonyms. Using 'local' outside a function is an error, so IMHO this command is completely redundant. It _would_ make some sense, however, if its counterpart 'global' existed, as it could help clarify the intended usage of the variable. Bernd -- Bernd Egginkhttp://sudrala.de $ vars () { var1=123; local var2=456; } $ vars $ echo "var1=$var1 "var2=$var2" var1=123 var2= How is that "the other way around"? (Sorry, something went wrong with the last reply) What I meant is that variables _declared_ in functions are always global. -- Bernd Eggink http://sudrala.de
Re: add a way to declare global variables
Am 12.12.2009 15:25, schrieb DennisW: On Dec 12, 4:24 am, Bernd Eggink wrote: Am 12.12.2009 02:11, schrieb Matthew Woehlke: konsolebox wrote: I hope the development team will also consider adding a way in bash to declare global variables inside a function perhaps either with an option in typeset or declare like -g (same as zsh) and/or a builtin function like global as similar to local. I thought variables in functions were /always/ global unless declared local? It's the other way round. Regarding typeset and declare, the man page says: " When used in a function, makes each name local, as with the local command. " So within a function, typeset, declare, and local are synonyms. Using 'local' outside a function is an error, so IMHO this command is completely redundant. It _would_ make some sense, however, if its counterpart 'global' existed, as it could help clarify the intended usage of the variable. Bernd -- Bernd Egginkhttp://sudrala.de $ vars () { var1=123; local var2=456; } $ vars $ echo "var1=$var1 "var2=$var2" var1=123 var2= How is that "the other way around"? -- Bernd Eggink http://sudrala.de
Re: add a way to declare global variables
Am 12.12.2009 11:24, schrieb Bernd Eggink: Am 12.12.2009 02:11, schrieb Matthew Woehlke: konsolebox wrote: I hope the development team will also consider adding a way in bash to declare global variables inside a function perhaps either with an option in typeset or declare like -g (same as zsh) and/or a builtin function like global as similar to local. I thought variables in functions were /always/ global unless declared local? It's the other way round. Regarding typeset and declare, the man page says: " When used in a function, makes each name local, as with the local command. " So within a function, typeset, declare, and local are synonyms. To avoid misunderstandings, let me add that you are right (only) with respect to variables being used _without_ declaration. The problem is that associative arrays are the only kind of variables that _must_ be declared, since something like "a[foo]=bar" without a preceding declaration would create an indexed array (and set a[0] to "bar"). Bernd -- Bernd Eggink http://sudrala.de
Re: add a way to declare global variables
Am 10.12.2009 10:40, schrieb konsolebox: I hope the development team will also consider adding a way in bash to declare global variables inside a function perhaps either with an option in typeset or declare like -g (same as zsh) and/or a builtin function like global as similar to local. I second that. I'm missing this feature badly. Presently, you can only get around this restriction by using a lot of ugly and dangerous 'eval's. Bernd -- Bernd Eggink http://sudrala.de
Re: add a way to declare global variables
Am 12.12.2009 02:11, schrieb Matthew Woehlke: konsolebox wrote: I hope the development team will also consider adding a way in bash to declare global variables inside a function perhaps either with an option in typeset or declare like -g (same as zsh) and/or a builtin function like global as similar to local. I thought variables in functions were /always/ global unless declared local? It's the other way round. Regarding typeset and declare, the man page says: " When used in a function, makes each name local, as with the local command. " So within a function, typeset, declare, and local are synonyms. Using 'local' outside a function is an error, so IMHO this command is completely redundant. It _would_ make some sense, however, if its counterpart 'global' existed, as it could help clarify the intended usage of the variable. Bernd -- Bernd Eggink http://sudrala.de
Re: Use of pipe in $(< filename | program) returns null
Am 28.11.2009 06:35, schrieb r...@saturn.syslang.net: Description: use of $(< filename | program) does not work. It either should or it should be properly documented. The problem also happens on bash4. Repeat-By: qq=$(< /etc/passwd | grep sys) echo $qq # result is null Fix: Either fix the docs to tell people that a pipe is not allowed or fix the code to allow it. The problem is not the pipe but the fact that 'command which does nothing. If you want 'program' to read from 'file', use 'program Bernd -- Bernd Eggink http://sudrala.de
Re: Wrong 'declare -A' causes segfault
Am 26.11.2009 01:47, schrieb Chet Ramey: Bernd Eggink wrote: GNU bash, version 4.0.35(1)-release (i686-pc-linux-gnu) The following syntactically wrong declaration causes a segmentation fault: declare -A x=y It should issue an error message instead. It's not actually a syntax error. Hm, but the man page says, "Indexed array assignments do not require the bracket and subscript." This sounds like the syntax above is valid for indexed arrays, but not for associative arrays. Maybe the documentation should be corrected then. Bernd -- Bernd Eggink http://sudrala.de
Wrong 'declare -A' causes segfault
GNU bash, version 4.0.35(1)-release (i686-pc-linux-gnu) The following syntactically wrong declaration causes a segmentation fault: declare -A x=y It should issue an error message instead. Regards, Bernd -- Bernd Eggink http://sudrala.de
Re: Strange compgen behaviour
Mathias Dahl schrieb: Hm, compgen appears to behave strange if words contain whitespace. However, you don't need it, as you build the list yourself. Try this: _mm2() { local cur files cur=${COMP_WORDS[COMP_CWORD]} files=$(find /home/mathias/Videos/movies/ -iname "$cur*.avi" -type f -printf "%P\n") local IFS=$'\n' COMPREPLY=($files) } Ah, you're right of course, I can do the matching myself. I have yet another version working now (had to change your latest suggestion and use grep for matching because -name does not like full paths which becomes the case here): _mm() { local cur files COMPREPLY=() cur="${COMP_WORDS[COMP_CWORD]}" files=$(find /home/mathias/Videos/movies/ -iname "*.avi" -type f - printf "%p\n" | grep "${cur}") local IFS=$'\n' COMPREPLY=(${files}) } complete -o filenames -F _mm mm Now, this works almost. The remaining problem is that because `find' finds file in subdirs (which I want, otherwise I could add the - maxdepth option) as well, the `-o filenames' argument to `complete' does not play well with it. I see the names of files in subdirs listed when I type TAB (without path) but can never pick them without knowing the name of the folder they are in. Hm, I can't see any problem here. My version lets you pick any file in any subdir by simply typing the name (or part of it) without the directory part. After all, 'find -name' matches names, not paths (if you want to match full paths, use 'find -path'). I'd also rather use printf "%P\n" (capital P) instead of %p, the results look nicer (IMHO). Regards, Bernd -- Bernd Eggink http://sudrala.de
Re: Strange compgen behaviour
Chet Ramey schrieb: Hm, compgen appears to behave strange if words contain whitespace. Well, it splits the argument to -W on $IFS as documented. What other strange behavior do you see? For example, this: function _aha { local list="a b:c d:e f" COMPREPLY=($(IFS=: compgen -W "$list")) } complete -F _aha aha Typing aha cycles through 6 items a, b, c, d, e, f, whereas I would expect 3 items 'a b', 'c d', 'e f'. It looks like compgen splits the argument to -W on $IFS _and_ whitespace. Or am I missing something? Regards, Bernd -- Bernd Eggink http://sudrala.de
Re: Strange compgen behaviour
Mathias Dahl schrieb: It depends heavily on how the variables IFS and zf are set. From 'man bash': -W wordlist The wordlist is split using the characters in the IFS special variable as delimiters, and each resultant word is expanded. The possible completions are the members of the resultant list which match the word being completed. I used a newline since the original listing comes from `find'. You didn't say how you assigned the variable zf. If you simply did zf=$(ls /home/mathias/Videos/movies/*), the "Brazil" line will be split into 4 words instead of 1. However, your output suggest that you somehow managed to combine all file names to a single word starting with Harry.Potter. Yes, that could be the case. Try this: Choose a character which doesn't appear in any file name, e.g., ':'. list=$(printf "%s:" /home/mathias/Videos/movies/*) IFS=: compgen -W "$list" -- $zc That works, thanks! However, I also want files from sub folders to be found, so I use `find' to list them. Here is my latest attempt, using the idea of setting IFS to `:': _mm2() { local cur files COMPREPLY=() cur="${COMP_WORDS[COMP_CWORD]}" files=$(find /home/mathias/Videos/movies/ -iname '*.avi' -type f - printf "%p:") OLDIFS=$IFS IFS=: COMPREPLY=($(compgen -W "${files}" -- ${cur})) IFS=$OLDIFS } complete -o filenames -F _mm2 mm Looks like it should work but it does not. Typing mm gives the listing and completes all the way to the path, but if I add B again it does not match Brazil. Hm, compgen appears to behave strange if words contain whitespace. However, you don't need it, as you build the list yourself. Try this: _mm2() { local cur files cur=${COMP_WORDS[COMP_CWORD]} files=$(find /home/mathias/Videos/movies/ -iname "$cur*.avi" -type f -printf "%P\n") local IFS=$'\n' COMPREPLY=($files) } Regards, Bernd -- Bernd Eggink http://sudrala.de
Re: Strange compgen behaviour
Mathias Dahl schrieb: Hi fellow bashers! I am trying to add some completion to a command. The completion should list all movies I have in a certain folder, regardless if I am in that folder or not. I have kind of got it to work in several variants but all have some issue. The current problem I am looking at is very strange. I have isolated it down to a strange behaviour with compgen. Let's see if I can describe it clearly enough: zf contains the list of movie file names zc is the current input, in my case "/home/mathias/Videos/movies/H" $ compgen -W "${zf}" -- ${zc} Here is the output: /home/mathias/Videos/movies/Harry.Potter... /home/mathias/Videos/movies/Harry.Potter... /home/mathias/Videos/movies/Harry.Potter... /home/mathias/Videos/movies/Harry.Potter... /home/mathias/Videos/movies/Harry.Potter... /home/mathias/Videos/movies/Brazil (Terry Gilliam, 1985).avi /home/mathias/Videos/movies/Ice.Age.2... /home/mathias/Videos/movies/True.Blood.S01... /home/mathias/Videos/movies/True.Blood.S01... It depends heavily on how the variables IFS and zf are set. From 'man bash': -W wordlist The wordlist is split using the characters in the IFS special variable as delimiters, and each resultant word is expanded. The possible completions are the members of the resultant list which match the word being completed. You didn't say how you assigned the variable zf. If you simply did zf=$(ls /home/mathias/Videos/movies/*), the "Brazil" line will be split into 4 words instead of 1. However, your output suggest that you somehow managed to combine all file names to a single word starting with Harry.Potter. Try this: Choose a character which doesn't appear in any file name, e.g., ':'. list=$(printf "%s:" /home/mathias/Videos/movies/*) IFS=: compgen -W "$list" -- $zc Regards, Bernd -- Bernd Eggink http://sudrala.de
Re: Help with script - doesn't work properly from cron
Erik Olof Wahlstrom schrieb: Hello - I am having a problem with a backup script that I have put together - when I run it as root from the terminal, it works as expected (with one caveat); however, when cron runs it, the daily backup folder is created but no files are deposited into that folder... Here is the script: #!/bin/bash BACKUP_DIR="/media/disk/AUTOMATED_BACKUPS/DB_DAILY" CURRENT_DIR=$BACKUP_DIR/`date +%d` DATABASES="$(/usr/bin/mysql -uUsername -pPassword -Bse 'show databases')" echo 'Backing up databases: '$DATABASES if [ -e "$CURRENT_DIR" ] then cd $CURRENT_DIR /bin/rm * else /bin/mkdir $CURRENT_DIR cd $CURRENT_DIR fi for DB in $DATABASES do /usr/bin/mysqldump -uroot -pHardAsMySql321 "$DB" | bzip2 > "$DB"_`date +%Y-%m-%d_%k.%M`".sql.bz2" done exit 0 Can any skilled eyes see why this doesn't work when it is run from the roots crontab? The reason may be that crontab commands are run with "/bin/sh -c command" (Bourne shell mode). Try changing the crontab entry to "/bin/bash command". Additionally, when I run the script as root in the terminal, I get the following output: Backing up databases: information_schema db1 db2 db3 /bin/rm: cannot remove `*': No such file or directory Is there a better way to clear out last months files before making the current backups? You could replace the whole if-then-else clause by mkdir -p $CURRENT_DIR cd $CURRENT_DIR rm -f * provided the options are supported on your system. Regards, Bernd -- Bernd Eggink http://sudrala.de
Re: bash prompt misbehaving - correction.
Chris Jones schrieb: ... > After retrieving a command from the history via a CTRL-R, an ensuing CTRL-A moves the cursor to somewhere in the middle of the prompt and CTRL-E is short of the retrieved command's end by some ten characters. ... PS1="\[\033[0;41m\][\$(date +%T)]...@\h:\w]\\$\[\033[0m\] " This works correctly with bash 4.0.24. Regards, Bernd -- Bernd Eggink http://sudrala.de
Re: Memory leak in for loops
Jan Schampera schrieb: Sandino Araico Sánchez wrote: 1. #!/bin/bash 2. 3. for i in {0..c} ; do 4. echo $i > /dev/null 5. done Repeat-By: Run the script above and the process starts leaking memory very fast. You know what a memory *leak* is, yes? mallocs() without proper free()s. What you mean is that your memory is used. Feel free to calculate the memory that is needed to store the string representation of {0..15000}, I think you will get a number near your RAM size. J. ... and try for (( i = 0; i < 15000; ++i )) do echo $i > /dev/null done instead. Consumes nearly no memory at all. Cheers, Bernd -- Bernd Eggink http://sudrala.de
Re: Crash in hashlib.c
Chet Ramey schrieb: Bernd Eggink wrote: Version: GNU bash, Version 4.0.17(1)-release (i686-pc-linux-gnu) (plus newline-shellmeta patch). A script which uses, among other things, 3 associative arrays and a coprocess, crashes reproducibly with an allocation error: malloc: hashlib.c:306: assertion botched free: called with unallocated block argument Abbruch... Program received signal SIGABRT, Aborted. 0xe424 in __kernel_vsyscall () Appended is a stack trace. Hope it helps. Unfortunately not much. If you could post a portion of the script that reproduces the error, that would be better. Well, (un)fortunately after a reboot the crash no longer happens. Maybe the memory had been corrupted by some other program (possibly lftp, which I used as a co-process). Bernd -- Bernd Eggink http://sudrala.de
Crash in hashlib.c
Version: GNU bash, Version 4.0.17(1)-release (i686-pc-linux-gnu) (plus newline-shellmeta patch). A script which uses, among other things, 3 associative arrays and a coprocess, crashes reproducibly with an allocation error: malloc: hashlib.c:306: assertion botched free: called with unallocated block argument Abbruch... Program received signal SIGABRT, Aborted. 0xe424 in __kernel_vsyscall () Appended is a stack trace. Hope it helps. Regards, Bernd -- Bernd Eggink http://sudrala.de malloc: hashlib.c:306: assertion botched free: called with unallocated block argument Abbruch... Program received signal SIGABRT, Aborted. 0xe424 in __kernel_vsyscall () (gdb) bt #0 0xe424 in __kernel_vsyscall () #1 0xb7dc9580 in raise () from /lib/libc.so.6 #2 0xb7dcadb8 in abort () from /lib/libc.so.6 #3 0x08081727 in programming_error (format=0x8117f50 "free: called with unallocated block argument") at error.c:175 #4 0x080fc81b in xbotch (mem=0x8101558, e=2, s=0x8117f50 "free: called with unallocated block argument", file=0x81027af "hashlib.c", line=306) at malloc.c:319 #5 0x080fd347 in internal_free (mem=0x8101558, file=0x81027af "hashlib.c", line=306, flags=1) at malloc.c:876 #6 0x080fdb7f in sh_free (mem=0x8101558, file=0x81027af "hashlib.c", line=306) at malloc.c:1202 #7 0x080b841e in sh_xfree (string=0x8101558, file=0x81027af "hashlib.c", line=306) at xmalloc.c:190 #8 0x0809be16 in hash_flush (table=0x81c7f28, free_data=0) at hashlib.c:306 #9 0x080a703b in assoc_dispose (hash=0x81c7f28) at assoc.c:57 #10 0x0807d8a0 in dispose_variable_value (var=0x81c7a48) at variables.c:2584 #11 0x0807d8f6 in dispose_variable (var=0x81c7a48) at variables.c:2598 #12 0x0807f890 in push_func_var (data=0x81c7a48) at variables.c:3781 #13 0x0809bdd8 in hash_flush (table=0x81c7c28, free_data=0x807f7b8 ) at hashlib.c:303 #14 0x0807f904 in pop_var_context () at variables.c:3803 #15 0x0807fbc1 in pop_context () at variables.c:3938 #16 0x0809f43b in unwind_frame_run_internal (tag=0x810114f "function_calling", ignore=0x0) at unwind_prot.c:291 #17 0x0809f0d2 in without_interrupts (function=0x809f39d , arg1=0x810114f "function_calling", arg2=0x0) at unwind_prot.c:106 #18 0x0809f14f in run_unwind_frame (tag=0x810114f "function_calling") at unwind_prot.c:134 #19 0x08078a89 in execute_function (var=0x815b0c8, words=0x8168f28, flags=0, fds_to_close=0x8166968, async=0, subshell=0) at execute_cmd.c:4078 #20 0x08078ef2 in execute_builtin_or_function (words=0x8168f28, builtin=0, var=0x815b0c8, redirects=0x0, fds_to_close=0x8166968, flags=0) at execute_cmd.c:4271 #21 0x08077ffc in execute_simple_command (simple_command=0x818fc68, pipe_in=-1, pipe_out=-1, async=0, fds_to_close=0x8166968) at execute_cmd.c:3724 #22 0x08072ed9 in execute_command_internal (command=0x818fd68, asynchronous=0, pipe_in=-1, pipe_out=-1, fds_to_close=0x8166968) at execute_cmd.c:724 #23 0x08075280 in execute_connection (command=0x818ec68, asynchronous=0, pipe_in=-1, pipe_out=-1, fds_to_close=0x8166968) at execute_cmd.c:2173 #24 0x08073216 in execute_command_internal (command=0x818ec68, asynchronous=0, pipe_in=-1, pipe_out=-1, fds_to_close=0x8166968) at execute_cmd.c:880 #25 0x080731e7 in execute_command_internal (command=0x81a7a08, asynchronous=0, pipe_in=-1, pipe_out=-1, fds_to_close=0x8166968) at execute_cmd.c:872 #26 0x08078a47 in execute_function (var=0x815a488, words=0x8168d28, flags=0, fds_to_close=0x8166968, async=0, subshell=0) at execute_cmd.c:4056 #27 0x08078ef2 in execute_builtin_or_function (words=0x8168d28, builtin=0, var=0x815a488, redirects=0x0, fds_to_close=0x8166968, flags=0) at execute_cmd.c:4271 #28 0x08077ffc in execute_simple_command (simple_command=0x81665a8, pipe_in=-1, pipe_out=-1, async=0, fds_to_close=0x8166968) at execute_cmd.c:3724 #29 0x08072ed9 in execute_command_internal (command=0x8166588, asynchronous=0, pipe_in=-1, pipe_out=-1, fds_to_close=0x8166968) at execute_cmd.c:724 #30 0x080726bb in execute_command (command=0x8166588) at execute_cmd.c:369 #31 0x08076cc5 in execute_if_command (if_command=0x81664a8) at execute_cmd.c:3067 #32 0x0807313d in execute_command_internal (command=0x8166488, asynchronous=0, pipe_in=-1, pipe_out=-1, fds_to_close=0x8159688) at execute_cmd.c:832 #33 0x08075280 in execute_connection (command=0x8154608, asynchronous=0, pipe_in=-1, pipe_out=-1, fds_to_close=0x8159688) at execute_cmd.c:2173 #34 0x08073216 in execute_command_internal (command=0x8154608, asynchronous=0, pipe_in=-1, pipe_out=-1, fds_to_close=0x8159688) at execute_cmd.c:880 #35 0x080731e7 in execute_command_internal (command=0x8159a48, asynchronous=0, pipe_in=-1, pipe_out=-1, fds_to_close=0x8159688) at execute_cmd.c:872 #36 0x08078a47 in execute_function (var=0x8159c08, words=0x8164268, flags=0, fds_to_close=0x8159688, async=0, subshell=0
Re: Bug: 'case' in command substitution not handled correctly
Chet Ramey schrieb: Bernd Eggink wrote: GNU bash, Version 4.0.17(1)-release (i686-pc-linux-gnu) The shell doesn't recognize the closing parenthesis of a command substitution if a 'case' command is included and 'esac' is preceded by newline. Example: x=$(case $a in (1) echo one esac ) Try the attached patch. A newline really is a shell meta-character. That fixes it, thanks. Bernd -- Bernd Eggink http://sudrala.de
Bug: 'case' in command substitution not handled correctly
GNU bash, Version 4.0.17(1)-release (i686-pc-linux-gnu) The shell doesn't recognize the closing parenthesis of a command substitution if a 'case' command is included and 'esac' is preceded by newline. Example: x=$(case $a in > (1) echo one > esac > ) > You can enter as many ')' as you like, the shell still wants another one. This variant works, however: x=$(case $a in (1) echo one;esac ) Regards, Bernd -- Bernd Eggink http://sudrala.de
Re: feature-request: brief syntax for $(type -p somecommand)
Mike Coleman schrieb: On Thu, Apr 2, 2009 at 11:57 AM, Chris F.A. Johnson wrote: If that's what you want, you can include it in the function: p() { _p=$( type -p "$@" ) [ -n "$_p" ] && ls -l $_p } This is more or less what I'm doing now, with one function for each command. I suppose the command could be an argument, too, so that one could run $ p ls somecommand $ p ldd somecommand $ p strings somecommand $ p file somecommand $ p nm somecommand though there's no command completion this way. I guess I could add that, too. One problem, though, like the "wait for slot" feature I suggested a few months ago, is that something like this is quite a bit more useful when it's available everywhere (without having to drag one's bash library around). I have a more universal function (also named p) here: http://www.sudrala.de/en_d/shell-cmdexp.html Maybe it is of use for you, too. Regards, Bernd -- Bernd Eggink http://sudrala.de
Re: reference dir ../common in script
Jan Schampera schrieb: OnTheEdge wrote: I'm trying to check for a directory and create it if it doesn't exist as follows: CommonDir="../common" if [ -d ${CommonDir} ]; then mkdir "${CommonDir}" fi It works from the command line, but my script doesn't seem to like it and I can't figure it out. Thanks for any help, Duane You have a wrong logic. This script will mkdir if it exists. use [ ! -d "${CommonDir}" ] Or use mkdir -p $CommonDir Bernd -- Bernd Eggink http://sudrala.de
Re: Behaviour of cd changed?
Chet Ramey schrieb: Bernd Eggink wrote: I'm still having problems with the cd builtin. In bash 3, the commands cd cd "" both changed to the user's home directory. In bash 4 (with patch "save-current-token" applied) cd "" does nothing. Bug or feature? I get the same behavior from bash-3.2.48 and bash-4.0: canonicalizing "" (since it's not an absolute pathname) results in $PWD, and the cd has no effect. If you run cd -P "" to avoid canonicalization, you get an error. Make sure you're running `builtin cd' when you test to avoid the effect of any function you've defined. Sorry, my mistake. In a moment of mental absence I had changed builtin cd "@" to builtin cd "*" This caused the change in behaviour and is wrong, of course. Regards, Bernd -- Bernd Eggink http://sudrala.de
Behaviour of cd changed?
I'm still having problems with the cd builtin. In bash 3, the commands cd cd "" both changed to the user's home directory. In bash 4 (with patch "save-current-token" applied) cd "" does nothing. Bug or feature? Regards, Bernd -- Bernd Eggink http://sudrala.de
Re: Problem with function cd in bash 4.0
Chet Ramey schrieb: Bernd Eggink wrote: I normally wrap the builtin cd into a function cd, which does some additional things and then calls the builtin. Example: function cd { local list=$(echo *.bui) # ... builtin cd "$1" } I have a PS1 like this: PS1="\\w \$ " With bash 3, this worked well; cd-ing into a directory changed the prompt immediately. With bash 4, however, the prompt keeps unchanged after a call to cd and only gets adjusted after the _next_ command. I noticed that this depends on a subshell being used in the function. Without that, it behaves as before. Is that a bug? I can get the intended behaviour by putting eval "PS1='$PS1'" at the end of the function, but that's a rather ugly workaround. Yep, it's a bug. Try the attached patch; it works for me. Works for me, too. Thanks! Bernd -- Bernd Eggink http://sudrala.de
Problem with function cd in bash 4.0
I normally wrap the builtin cd into a function cd, which does some additional things and then calls the builtin. Example: function cd { local list=$(echo *.bui) # ... builtin cd "$1" } I have a PS1 like this: PS1="\\w \$ " With bash 3, this worked well; cd-ing into a directory changed the prompt immediately. With bash 4, however, the prompt keeps unchanged after a call to cd and only gets adjusted after the _next_ command. I noticed that this depends on a subshell being used in the function. Without that, it behaves as before. Is that a bug? I can get the intended behaviour by putting eval "PS1='$PS1'" at the end of the function, but that's a rather ugly workaround. Regards, Bernd -- Bernd Eggink http://sudrala.de
Re: echo $s{2,3}
jida...@jidanni.org schrieb: What happened to 2,3? Poof, gone. $ s=a; echo $s{ $s{} $s} $s{1} $s{2,3} ${s}{4,5} a{ a{} a} a{1} a4 a5 As the manual says, brace expansion is performed before any other expansions. So $s{2,3} expands to $s2 $s3, and that expands to nothing if neither s2 nor s3 are set. Regards, Bernd -- Bernd Eggink http://sudrala.de
Re: =~ behaves differently in bash 3.2 and 3.0
Clark J. Wang schrieb: In bash 3.0.14, the condition [[ file.txt =~ .*\\.txt\$ ]] returns TRUE but in 3.2.39 it returns FALSE. But with the shopt option `compat31' set it also returns TRUE. Is that reasonable? In the bash manual, `compat31' makes sense only for quoted patterns. The string .*\\.txt\$ is considered to be quoted? I guess it doesn't work in 3.2.39 because there are to many backslashes: \\. tests for a literal \ followed by any character. \$ tests for a literal $ right after txt So this works as expected: [[ file.txt =~ .*\.txt$ ]]# condition is true Don't know about 3.0.14, but it looks like it performed expansion on the regexp, while 3.2.39 leaves it unchanged. Regards, Bernd -- Bernd Eggink http://sudrala.de
Re: implementing flow control in bash
Tony Zanella schrieb: Hello all, I'm sure this isn't a bug, but just my inability to wrap my head around enough of bash flow control: I wrote the following shell script to find all gifs in a directory. Then use "identify" from imagemagick to grab the gif width. Then, print the image name and width to a file. for i in `find . -name \*gif`; do identify -format "$i %w" $i; done results.txt Then, I used a ruby script to cull only those images with a width over 570 pixels. So, problem solved, but I wanted to see if I could do it all in bash. More specifically, (if this makes sense) I want to "do identify -format "$i %w" $i" only for those "$i %w" where "%w" is > 570. The above script will give me output like: image1.gif 360 image2.gif 780 But I want it to give me: image1.gif 360 In pseudo-code, I want something like: for i in `find . -name \*gif`; do identify -format "$i %w" $i if [%w 570]; done > results.txt for i in $(find -name '*.gif') do w=$(identify -format %w $i) (( w > 570 )) && echo "$i $w" done Hope that helps, Bernd -- Bernd Eggink http://sudrala.de
Re: running source twice wont use arguments
pgb schrieb: I have a bash script that I run using source because I want to be left in the environment that the script sets up after running the script. The script takes a few arguments and sets up an environment for me that includes library paths, classpaths, JAVA_HOME, appends to the PATH, creates and populates a local workspace etc. I call the script in the following manner source setup_env -o -w testdir The -o argument is to wipe out the workspace if it already exists (unconditionally) and the -w provides the name of the workspace to setup. The first time I run the script it runs just fine and all the arguments work as expected, the environment is all setup etc. However, if I immediately run the command again all the arguments are completely ignored source setup_env -o -w testdir The script runs but fails because it's not reading in the args for some reason. As a matter of fact, if I give an argument that doesn't even make sense (-garbage) , the script runs but again the arguments are ignored so it ultimately fails. I searched the forum but did not find a related post. If I don't source the script and run it from the command line, it works both times, but then my environment is not mantained after the script runs so that's not a good idea What in my environment, post-script-run is making the second source not "see" the command line arguments? You probably use getopts, which changes the variable OPTIND in the current environment. The value of this variable is not automatically reset if you start another getopts loop, you have to do it yourself: OPTIND=1 while getopts "ow:" opt do ... done Regards, Bernd -- Bernd Eggink http://sudrala.de
Re: Bash prints syntax error when command in $(...) contains case-esac
Juergen Gohlke schrieb: Configuration Information [Automatically generated, do not change]: Machine: i686 OS: cygwin Compiler: gcc Compilation CFLAGS: -DPROGRAM='bash.exe' -DCONF_HOSTTYPE='i686' -DCONF_OSTYPE='cygwin' -DCONF_MACHTYPE='i686-pc-cygwin' -DCONF_VENDOR='pc' -DLOCALEDIR='/usr/share/locale' -DPACKAGE='bash' -DSHELL -DHAVE_CONFIG_H -DRECYCLES_PIDS -I. -I/home/eblake/bash-3.2.9-11/src/bash-3.2 -I/home/eblake/bash-3.2.9-11/src/bash-3.2/include -I/home/eblake/bash-3.2.9-11/src/bash-3.2/lib -O2 -pipe uname output: CYGWIN_NT-5.0 JONA 1.5.24(0.156/4/2) 2007-01-31 10:57 i686 Cygwin Machine Type: i686-pc-cygwin Bash Version: 3.2 Patch Level: 9 Release Status: release Description: If a command in $(...) contains a case-esac construction, the bash prints a syntax error instead of executing the code: bash: syntax error near unexpected token `;;' Repeat-By: A simple example is: x=$(a=4; case $a in 3) echo a=3;; 4) echo a=4;; esac) (typed in an interactive shell or being part of a shell script). The same error has been seen on Windows Vista, Windows XP and Windows2000. The same error has been seen with an earlier version of bash, i.e. 2.05b.0(8)-release If $(...) is replaced by `...`, it works. The problem is caused by the semi-parenthesized case labels 3) and 4). Bash matches the first unpaired right paren (after the 3) with the last unpaired left paren (in $( ). Using (3) and (4) instead makes the example work. Unpaired parens are hideous anyway, IMHO. Regards, Bernd -- Bernd Eggink [EMAIL PROTECTED] http://sudrala.de
Expanding an undefined array
Is the following difference intentional, a bug, or do I miss something? unset a set -- "[EMAIL PROTECTED]" echo $# Output: 0 typeset a set -- "[EMAIL PROTECTED]" echo $# Output: 1 The man page says, "If the word is double-quoted, ... [EMAIL PROTECTED] expands each element of name to a separate word. When there are no array members, [EMAIL PROTECTED] expands to nothing." It doesn't mention a difference between an empty and an unset variable in this context. As a quoted 'nothing' normally counts 1 word, the 'nothing' in the first example appears to be some kind of 'super-nothing'. Regards, Bernd -- Bernd Eggink [EMAIL PROTECTED] http://sudrala.de
Re: PATH value doesn't get updated
Peter Volkov schrieb: Better way to check if shell is login is: $ shopt | grep login_shell login_shell on You don't even have to call an external program: [[ $(shopt -p login_shell) == *-s* ]] Regards, Bernd -- Bernd Eggink [EMAIL PROTECTED] http://sudrala.de
Re: Which Bash
Charlse Darwin schrieb: $ echo $BASH_VERSION 2.05b.0(1)-release $ bash --version GNU bash, version 3.2.33(1)-release (powerpc-apple-darwin8.11.0) Copyright (C) 2007 Free Software Foundation, Inc. $ which bash /opt/local/bin/bash $ # Which bash is being used by the system; 3.2.33(1)-release or 2.05b.0(1)-release? Looks like there are at least 2 versions on your system: Your login shell is probably bash-2.05b, while /opt/local/bin/bash (the latest version) is found via $PATH. Check your account data and PATH setting to verify it. Regards, Bernd -- Bernd Eggink [EMAIL PROTECTED] http://sudrala.de
Re: Bash 3.2.25 not expanding subscript...
Brad Diggs schrieb: In short the bug is the result of failure to expand the subscript of an array if the subscript is a variable. The following script should return a list of files with a preceding (File <#>: ). However, it does not work that way because the integer variable (${d}) used in the subscript of the array statement (FileList[${d}]=${File}) does not get properly expanded. #!/bin/bash declare -a FileList=('') declare -i d=0 ls -1| while read File do FileList[${d}]=${File} d=$((10#${d}+1)) done This is normal bash behaviour, see FAQ E4. As bash executes _all_ parts of a pipe in subshells (in contrast to ksh, where the last component is executed in the current shell), the variable 'FileList' being assigned here is local to the subshell. After the loop the variable 'FileList' declared in line 1 (which happens to have the same name, but that doesn't matter) is unchanged. Try this instead: while read File do FileList[d]=$File (( d=d+1 )) done <<<"$(ls -1)" Greetings, Bernd -- Bernd Eggink [EMAIL PROTECTED] http://sudrala.de
Re: capturing sub-expressions?
Paul Jarc schrieb: Bernd Eggink <[EMAIL PROTECTED]> wrote: My impression is that the pattern lookup depends on whether or not a !' is involved. If the pattern does not contain a '!', the shell looks for matching substrings, from left to right. If it contains a '!', the value as a whole is matched. It looks for substrings in both cases - specifically, the longest matching substring, which might happen to be the entire string. With !(), that is often the case. x=12ab34; echo ${x//+([0-9])/X}# prints XabX x=12ab34; echo ${x//!(+([0-9]))/X} # prints X If the same algorithm had been applied in the 2nd case, the first substring matching the pattern "not a sequence of at least one digit" would have been 'a' (or maybe 'ab'), and the output would have been 12Xb34' (or '12X34'). "12ab34" is also "not a sequence of at least one digit", so as the longest match, it is preferred. Thanks, that made it clear. The crucial point, that the longest match is preferred in any case, had slipped out of my mind (though I have been using this for decades...). Regards, Bernd -- Bernd Eggink [EMAIL PROTECTED] http://sudrala.de
Re: capturing sub-expressions?
Pierre Gaston schrieb: On Jan 28, 2008 4:00 AM, Linda Walsh <[EMAIL PROTECTED]> wrote: I was wondering -- in the bash substitute commands ${..%%|##|//} etc, is there a way to "capture" a subexpression, so that I can use the subexpression in the replacement string so I can end up 'only' with the the subexpression? I don't think so, you can only use =~ and BASE_REMATCH If the full expression was in a shellvar "Options", I thought about using something like: ${Option//!(expr)} which I hoped would have "!(expr) match anything but my desired expression, and the double "/" would say allow it to match multiple times, but it appears the "!()" construct is limited to pathname expansion? Presuming that is true (limited to pathname expansion), is there anyway to do it on Shell vars? !( ) is indeed not very intuitive, it is not limited to pathname expansion but it is not as interesting as it might seem. !(expr) will match anything that is not expr, for instance !(foo) will match f and bar, but it also match "fooa", the only thing that is not match is exactly "foo", which is useful if you do: "echo !(foo)" to list all the files except the one named "foo". Now if you use parameter expansion : var=fooa;echo ${var//!(foo)/b} # prints "b" because !(foo) matches "fooa" var=foo; echo ${var/!(foo)/b} # prints "bo" because !(foo) matches "fo" var=foo; echo ${var/!(foo)/b} # prints "bb" because !(foo) matches "fo" and "o" My impression is that the pattern lookup depends on whether or not a '!' is involved. If the pattern does not contain a '!', the shell looks for matching substrings, from left to right. If it contains a '!', the value as a whole is matched. Example: x=12ab34; echo ${x//+([0-9])/X}# prints XabX x=12ab34; echo ${x//!(+([0-9]))/X} # prints X If the same algorithm had been applied in the 2nd case, the first substring matching the pattern "not a sequence of at least one digit" would have been 'a' (or maybe 'ab'), and the output would have been '12Xb34' (or '12X34'). IMHO (please correct me if I'm wrong) this contradicts the usual meaning of the '!' operator and makes it nearly useless - except in the simple "echo !(foo)" case you mentioned. Bernd -- Bernd Eggink [EMAIL PROTECTED] http://sudrala.de
Re: capturing sub-expressions?
Linda Walsh schrieb: I was wondering -- in the bash substitute commands ${..%%|##|//} etc, is there a way to "capture" a subexpression, so that I can use the subexpression in the replacement string so I can end up 'only' with the the subexpression? If the full expression was in a shellvar "Options", I thought about using something like: ${Option//!(expr)} which I hoped would have "!(expr) match anything but my desired expression, and the double "/" would say allow it to match multiple times, but it appears the "!()" construct is limited to pathname expansion? Presuming that is true (limited to pathname expansion), is there anyway to do it on Shell vars? I keep confusing the path-matching regular expressions with string-matching expressions and keep getting disappointed when I'm re-reminded of the limitation...:-( There should be no difference between path-matching and string-matching expressions. Normally even nested extended patterns work with string matching. But, in fact, !(...) appears to not work like one would expect. The only case that looked correct to me is the trivial one ${x//!(*)}, which leaves $x unchanged. I'm not sure whether this is a bug or I (we) miss something. Interestingly, ksh behaves the same way. Can anybody clarify this? Regards, Bernd -- Bernd Eggink [EMAIL PROTECTED] http://sudrala.de
Re: Exit application with two function calls
[EMAIL PROTECTED] schrieb: Hi, I am working on a script and ran into an unusual program. Consider the following script which I called how.sh. = #!/bin/bash error () { echo -e "\n\terror: ${*}\n" exit; # kill $$ } check_file () { input="$*" if [ -e $input ]; then echo "$input" else error "invalid directory: $input" fi } chkFile="`check_file $1`" echo $chkFile echo "don't print" = When I run the command above I get this output: # ./how.sh /asdf error: invalid directory: /asdf don't print The reason is that `check_file` is executed in a subshell, so 'exit' just leaves the subshell, not the script itself. The command substitution is unnecessary anyway, as the result (if any) will simply be $1 itself. Thus, if you replace the main part by check_file $1 echo $1 it should work as expected. Regards, Bernd -- Bernd Eggink [EMAIL PROTECTED] http://sudrala.de
Re: Bash string substitution bug (?)
Chet Ramey schrieb: Bernd Eggink wrote: prompt: CLUSTER='1 2'; echo ${CLUSTER/${HOSTNAME/.*}} output: -bash: ${HOSTNAME: bad substitution Apparently bash interprets this as ${parameter/pattern/string} where pattern = ${HOSTNAME. Looks like a bug; it works in ksh. That is, in fact, what is happening. I'm not sure you can call it a bug, though -- bash is behaving exactly as documented. Where exactly is that documented? The only statement I can find in the documentation referring to this problem is: "When braces are used, the matching ending brace is the first `}' not escaped by a backslash or within a quoted string, and not within an embedded arithmetic expansion, command substitution, or parameter expansion." I may be wrong, but to me this means that the first opening brace matches the last closing one, and that the token ${HOSTNAME/.*} is a correct parameter expansion. Bernd -- Bernd Eggink [EMAIL PROTECTED] http://sudrala.de
Re: Bash string substitution bug (?)
Dmitry V Golovashkin schrieb: Description: unexpected bad substitution: enter the following simple list: prompt: CLUSTER='1 2'; echo ${CLUSTER/${HOSTNAME%%.*}} output: 1 2 the idea of the above line is to remove short HOSTNAME (without the trailing domain) from the CLUSTER - works fine (CLUSTER was assigned a dummy value - irrelevant) however the same operation with slash results in a bad substitution error. the substitution appears to be a valid one. prompt: CLUSTER='1 2'; echo ${CLUSTER/${HOSTNAME/.*}} output: -bash: ${HOSTNAME: bad substitution Apparently bash interprets this as ${parameter/pattern/string} where pattern = ${HOSTNAME. Looks like a bug; it works in ksh. As a workaround, you could use: H=${HOSTNAME/.*} echo ${CLUSTER/$H} Regards, Bernd -- Bernd Eggink [EMAIL PROTECTED] http://sudrala.de
Re: Comparison failure
Frans de Boer schrieb: You where both right. It's the '<' versus -lt. I tend to avoid -lt because I always run into errors using this. Beside, in previous versions of Bash it did not give me this problem. But, i will give it a try in other functions to see if it works now everywhere as expected. And yes, the use of these comparison tokens is not well documented either. I have always read the documentation that they where interchangeable, which is clearly not the case. Hm, 'man bash' clearly states in section "Conditional expressions" (that's what is included in [[ ... ]]): string1 < string2 True if string1 sorts before string2 lexicographically in the current locale. arg1 OP arg2 OP is one of -eq, -ne, -lt, -le, -gt, or -ge. These arithmetic binary operators return true if arg1 is equal to, not equal to, less than, less than or equal to, greater than, or greater than or equal to arg2, respectively. Arg1 and arg2 may be positive or negative integers. Personally, I like the bash documentation because it is complete and concise. Greetings, Bernd -- Bernd Eggink [EMAIL PROTECTED] http://sudrala.de
Re: regexp matching broken in bash-3.2.x?
Pierre Gaston schrieb: On 10/27/07, Bernd Eggink <[EMAIL PROTECTED]> wrote: Pavel Gorshkov schrieb: Description: Regexp matching seems to be broken since 3.2.0. Repeat-By: The following used to work in bash-3.1: $ [[ test =~ 't.*t' ]]; echo $? 1 It works without the quotes. Looks like they are taken literally instead of being removed. I, too, f.think it's a bug, as according to the docs, quote removal should be performed on the words between [[ and ]]. The behavior changed with 3.2, from the NEWS file: " Quoting the string argument to the [[ command's =~ operator now forces string matching, as with the other pattern-matching operators." Quoting removal is performed but [[ is not a normal command (it's a shell keyword) OK. While I don't consider this a good idea, at least the reference manual should be updated, which presently says: "Word splitting and filename expansion are not performed on the words between the `[[' and `]]'; tilde expansion, parameter and variable expansion, arithmetic expansion, command substitution, process substitution, _and quote removal_ are performed." Regards, Bernd -- Bernd Eggink [EMAIL PROTECTED] http://sudrala.de
Re: regexp matching broken in bash-3.2.x?
Pavel Gorshkov schrieb: Description: Regexp matching seems to be broken since 3.2.0. Repeat-By: The following used to work in bash-3.1: $ [[ test =~ 't.*t' ]]; echo $? 1 It works without the quotes. Looks like they are taken literally instead of being removed. I, too, think it's a bug, as according to the docs, quote removal should be performed on the words between [[ and ]]. Regards, Bernd -- Bernd Eggink [EMAIL PROTECTED] http://sudrala.de
Pattern replacement fails if string contains multibyte characters
This happens on a utf-8 based system (CRUX 2.3), LANG=de_DE.UTF-8: t="123abc456äöüABCD" echo ${t//[a-c]/} # output: 123456öüCD # (should be: "123456äöüABCD") echo ${t//[!a-c]/} # output: abcäAB # (should be: "abc") bash --version: GNU bash, version 3.2.25(1)-release (i686-pc-linux-gnu) Without multibyte chars, replacement works as expected. I looks like a bug, or am I misssing something? Regards, Bernd -- Bernd Eggink [EMAIL PROTECTED] http://sudrala.de
Re: Help with script --
t0nedef schrieb: echo "Please enter a network name" read ESSID if [ -n $ESSID ] You probably meant: if [ -z $ESSID ] then echo "unable to use a blank network name" exit $E_NOESSID fi Regards, Bernd -- Bernd Eggink [EMAIL PROTECTED] http://sudrala.de
Feature request: Escaping special characters in 'select' list
It would be nice if special characters in a 'select' list could be escaped by \[ and \], like in a prompt string. Presently, if a word in the list contains special characters (e.g., '^[[42m;aha^[[0m;'), the formatting of the list gets messed up. COLUMNS=50 select a in "^[[42maha^[[0m" one two three; do : ; done 1) aha 3) two 2) one 4) three #? (On a terminal, the first word has a green background). Regards, Bernd -- Bernd Eggink [EMAIL PROTECTED] http://monoped.de ___ Bug-bash mailing list Bug-bash@gnu.org http://lists.gnu.org/mailman/listinfo/bug-bash
Pattern replacement inconsistency
Configuration Information: 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/share/locale' -DPACKAGE='bash' -DSHELL -DHAVE_CONFIG_H -I. -I. -I./include -I./lib -O2 -march=i686 -pipe uname output: Linux Celsius 2.6.21.3 #1 SMP PREEMPT Fri May 25 10:14:50 CEST 2007 i686 GNU/Linux Machine Type: i686-pc-linux-gnu Bash Version: 3.2 Patch Level: 17 Release Status: release Description: If a is an array, ${a[*]//%pattern/replacement} and ${a[*]//#pattern/replacement} don't work. Both do nothing. The single-slash versions ${a[*]/%pattern/replacement} and ${a[*]/#pattern/replacement} work as expected. One could argue about using // in this context, but anyway the behavior is inconsistent in 2 ways: - The double-slash versions worked in 3.1. - The double-slash versions work in 3.2 if the pattern does _not_ start with % or #. Repeat-By: x=(a1 a2 a3) echo ${x[*]//%/y} # output: a1 a2 a3 echo ${x[*]//%2/y} # output: a1 a2 a3 echo ${x[*]//#/y} # output: a1 a2 a3 echo ${x[*]//#a/y} # output: a1 a2 a3 echo ${x[*]//a/y} # output: y1 y2 y3 -- Bernd Eggink [EMAIL PROTECTED] http://monoped.de ___ Bug-bash mailing list Bug-bash@gnu.org http://lists.gnu.org/mailman/listinfo/bug-bash