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: Real easy questions. Please answer
On Friday 25 September 2009 05:24:04 eatsubway wrote: sry i have a stupid question. I have a variable and need to know how many items are in it. for example: variable=abc xyz foo what program can i call to print out 3 right now im doing this... Counter() { echo $# } Counter $IDs but that just seems stupid Use an array, so you will even be able to store elements with spaces in them. -- D.
Re: Real easy questions. Please answer
On Thu, 24 Sep 2009, eatsubway wrote: sry i have a stupid question. I have a variable and need to know how many items are in it. for example: variable=abc xyz foo what program can i call to print out 3 right now im doing this... Counter() { echo $# } Counter $IDs but that just seems stupid That's a perfectly good way of doing it, but you will want to turn off filename expansion if there's a chance that the value may contain wildcards: set -f Counter $IDs set +f -- Chris F.A. Johnson, webmaster http://woodbine-gerrard.com === Author: Shell Scripting Recipes: A Problem-Solution Approach (2005, Apress)
Re: Strange compgen behaviour
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). When I try with %P it works (better). However, when I do that and use the -o filenames option I see only the filenames of the sub folders and sometimes that name does not reflect what it is as well as the folder does (if for example I have a folder called Cool Movie 2 and in it a file called thefile.avi). So, it seems I did not really want what I thought I wanted from the beginning :) The output I get now looks like this: ... filie_in_root_folder.avi Some sub folder/file_in_sub_folder.avi ... The only annoyance now is the hardcoded quoting (to handle spaces and other bad chars) I do using sed, but I guess I have to live with it. This has been an interesting topic! /Mathias
Re: Strange compgen behaviour
This has been an interesting topic! I thought I should share the final version as well: _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} | sed s/\\([][\\(\\) ,\']\\)/\\1/ g) local IFS=$'\n' COMPREPLY=(${files}) } complete -F _mm mm And the `mm' script needs to append the root folder, of course, like so: #!/bin/bash mplayer /home/mathias/Videos/movies/$1 Works quite well. Maybe it will be useful to someone else too. /Mathias
Re: Strange compgen behaviour
printf %q $filename will either insert backslashes in front of all the shell metacharacters, or $'...' quote the whole thing, or take some other action which renders a string safe. It's basically the opposite of eval. Interesting! Can I make it part of my pipe (in place of `sed') or need I change it to a for or while loop? This is what I have now: files=$(find /home/mathias/Videos/movies/ -iname *.avi -type f - printf %P\n | grep ${cur} | sed s/\\([][\\(\\) ,\']\\)/\\1/ g) /Mathias
Re: Strange compgen behaviour
Interesting! Can I make it part of my pipe (in place of `sed') or need I change it to a for or while loop? This is what I have now: files=$(find /home/mathias/Videos/movies/ -iname *.avi -type f - printf %P\n | grep ${cur} | sed s/\\([][\\(\\) ,\']\\)/\\1/ g) Got this to work: files=$(find /home/mathias/Videos/movies/ -iname *.avi -type f - printf %P\n | grep ${cur} | while read file; do printf %q $file echo done) With the %q option to printf it no longer accepts a \n so I needed the extra echo. /Mathias
Re: Strange compgen behaviour
Mathias Dahl mathias.d...@gmail.com writes: Got this to work: files=$(find /home/mathias/Videos/movies/ -iname *.avi -type f - printf %P\n | grep ${cur} | while read file; do printf %q $file echo done) With the %q option to printf it no longer accepts a \n so I needed the extra echo. printf %q\n works fine here. Also, grep ${cur} could probably be replaced by -path */${cur}*. Andreas. -- Andreas Schwab, sch...@linux-m68k.org GPG Key fingerprint = 58CA 54C7 6D53 942B 1756 01D3 44D5 214B 8276 4ED5 And now for something completely different.
Re: Bug in array populating does not respect quotes
Thank you for all and sorry for the noise, you were right. David. On Thu, Sep 24, 2009 at 6:38 PM, Chris F.A. Johnson ch...@cfajohnson.com wrote: On Thu, 24 Sep 2009, David Martin wrote: 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-pc-linux-gnu' -DCONF_VENDOR='pc' -DLOCALEDI$ uname output: Linux bristol 2.6.31 #10 SMP Thu Sep 10 17:59:29 CEST 2009 x86_64 GNU/Linux Machine Type: x86_64-pc-linux-gnu Bash Version: 4.0 Patch Level: 33 (debian bash-4.0-7) Release Status: release Description: When populating an array from a string in a variable does not handle quotes. Repeat-By: ~$ declare -a samplearray ~$ samplearray=( x y 'z k') ~$ echo ${samplearray[2]} z k ~$ samplestring=x y 'z k' ~$ samplearray=( $samplestring ) eval samplearray=( $samplestring ) ~$ echo ${samplearray[2]} 'z -- Chris F.A. Johnson, webmaster http://woodbine-gerrard.com === Author: Shell Scripting Recipes: A Problem-Solution Approach (2005, Apress)
Re: Strange compgen behaviour
Bernd Eggink wrote: 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 Tab 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? I don't think you're considering the interaction between compgen, command substitution, and compound array assignment. I'll use the assignment to `list' you used above for the explanation. compgen performs word splitting using $IFS and then outputs the results, one word per line: $ IFS=: compgen -W $list a b c d e f Command substitution takes that, chops off the last newline, and, since it's unquoted, performs word splitting using $IFS on the result: $ recho $(IFS=: compgen -W $list) argv[1] = a argv[2] = b argv[3] = c argv[4] = d argv[5] = e argv[6] = f If you want to preserve the embedded newlines, you have to quote the expansion (but see below): $ recho $(IFS=: compgen -W $list) argv[1] = a b^Jc d^Je f When performing compound array assignments, though, the words between the parens undergo all the shell word expansions, including word splitting: $ COMPREPLY=( $(IFS=: compgen -W $list) ) $ recho ${comprep...@]} argv[1] = a argv[2] = b argv[3] = c argv[4] = d argv[5] = e argv[6] = f So you can split on just the embedded newlines by setting $IFS: $ oifs=$IFS $ IFS=$'\n' COMPREPLY=( $(IFS=: compgen -W $list) ) $ IFS=$oifs $ recho ${comprep...@]} argv[1] = a b argv[2] = c d argv[3] = e f Remember to save and restore $IFS, though, since the assignment to it preceding the assignment to COMPREPLY will persist. Chet -- ``The lyf so short, the craft so long to lerne.'' - Chaucer ``Ars longa, vita brevis'' - Hippocrates Chet Ramey, ITS, CWRUc...@case.eduhttp://cnswww.cns.cwru.edu/~chet/
Re: Strange compgen behaviour
Chet Ramey schrieb: Bernd Eggink wrote: 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 Tab 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? I don't think you're considering the interaction between compgen, command substitution, and compound array assignment. I'll use the assignment to `list' you used above for the explanation. compgen performs word splitting using $IFS and then outputs the results, one word per line: $ IFS=: compgen -W $list a b c d e f Command substitution takes that, chops off the last newline, and, since it's unquoted, performs word splitting using $IFS on the result: $ recho $(IFS=: compgen -W $list) argv[1] = a argv[2] = b argv[3] = c argv[4] = d argv[5] = e argv[6] = f If you want to preserve the embedded newlines, you have to quote the expansion (but see below): $ recho $(IFS=: compgen -W $list) argv[1] = a b^Jc d^Je f When performing compound array assignments, though, the words between the parens undergo all the shell word expansions, including word splitting: $ COMPREPLY=( $(IFS=: compgen -W $list) ) $ recho ${comprep...@]} argv[1] = a argv[2] = b argv[3] = c argv[4] = d argv[5] = e argv[6] = f So you can split on just the embedded newlines by setting $IFS: $ oifs=$IFS $ IFS=$'\n' COMPREPLY=( $(IFS=: compgen -W $list) ) $ IFS=$oifs $ recho ${comprep...@]} argv[1] = a b argv[2] = c d argv[3] = e f Remember to save and restore $IFS, though, since the assignment to it preceding the assignment to COMPREPLY will persist. Chet, thanks for the clarification. It's actually quite obvious and I should have seen it myself. Regards, Bernd
Completion called within command substitution
Configuration Information [Automatically generated, do not change]: Machine: i486 OS: linux-gnu Compiler: gcc Compilation CFLAGS: -DPROGRAM='bash' -DCONF_HOSTTYPE='i486' -DCONF_OSTYPE='linux-gnu' -DCONF_MACHTYPE='i486-pc-linux-gnu' -DCONF_VENDOR='pc' -DLOCALEDIR='/usr/share/locale' -DPACKAGE='bash' -DSHELL -DHAVE_CONFIG_H -I. -I../bash -I../bash/include -I../bash/lib -g -O2 -Wall uname output: Linux myhost 2.6.26-2-686 #1 SMP Wed Aug 19 06:06:52 UTC 2009 i686 GNU/Linux Machine Type: i486-pc-linux-gnu Bash Version: 3.2 Patch Level: 39 Release Status: release When completing command substitution: $ a $(b cTAB the command completion for `a' is invoked, whereas I'd expect the command completion for `b' to be invoked. I would expect the same behaviour as with process substitution, which invokes the completion for `b': $ a (b cTAB Steps to reproduce: 1. Create functions `_a' and `_b' to complete `a' and `b': _a() { echo a; } _b() { echo b; } complete -F _a a complete -F _b b 2. Complete `b' within command substition: $ a $(b cTAB # This returns `a', where I'd expected `b'? 3. Complete `b' within process substitution: $ a (b cTAB # This returns `b' all right. Regards, Freddy Vulto http://fvue.nl