How to get filename completion without variable expansion?

2011-11-16 Thread jens . schmidt35
Hi,

I have the following problem:

(Environment or regular) variable FOO contains the path of existing directory 
"/foo".  When I have a file "/foo/bar" in that directory and when I press TAB 
in the following commandline ('|' denoting the cursor position)

  $ cat $FOO/b|

bash expands the commandline to

  $ cat /foo/bar |

However, I would like to expand it to

  $ cat $FOO/bar |

that is, keep the variable unexpanded, exactly as bash does not expand tilde 
characters during filename completion.

Any chances to achieve that with some shell or readline option?

Thanks and regards

Jens



Re: converting array to string by quoting each element for eval

2011-11-16 Thread Greg Wooledge
On Tue, Nov 15, 2011 at 07:46:14PM -0600, Peng Yu wrote:
> No. My real example use getopt.

**NEVER** use getopt(1).  It is broken.  It cannot be made to work
correctly.  Its entire design is flawed.

HP-UX getopt(1) says:

 WARNINGS
  getopt option arguments must not be null strings nor contain embedded
  blanks.


OpenBSD getopt(1) says:

BUGS
...
 Arguments containing whitespace or embedded shell metacharacters
 generally will not survive intact; this looks easy to fix but isn't.


You may safely use getopts (the builtin).  Never getopt.

> If I have each option in a separate
> argument, I need to know all the possible arguments to find, which is
> not a viable route.

*Why* do you "need to know" them?  What does that sentence even mean?

Is it because you have some NON-FIND OPTIONS after those?  Then why not
use the same trick that find(1) itself uses?  Use a sentinel argument
to indicate the end of the find-ish arguments.  ';' would be nicely
traditional.

Better still would be to rearrange the invocation so that the arbitrary
number of find-ish arguments are all at the end.

> How to pass the option "-type f -name '*'" correctly?

As four individual arguments, of course!

./myscript . -type f -name '*'

> /tmp$ ./not_convert_args_to_string.sh . "-type f -name '*'"

^^^ NOT THAT.

Please reread everything Chris said to you, because it all looked correct
to me.

If you *truly* need to serialize an array into a string and then retrieve
it back into an array later, there are ways to do this, but you have not
actually demonstrated a reason *why* you would ever need such a thing.
All you've shown so far is a constantly mutating vagueness in which you
keep trolling for some way to come up with a question which will convince
someone to tell you how to do something you shouldn't be doing.



Re: converting array to string by quoting each element for eval

2011-11-16 Thread Peng Yu
Hi Greg,

> **NEVER** use getopt(1).  It is broken.  It cannot be made to work
> correctly.  Its entire design is flawed.

I don't see these warnings in my systems (macports and ubuntu) (This
is version of getopt on macports and ubuntu is free, I don't see there
is a reason that getopt can not be ported to the two systems that you
mentioned). All I see that is relevant is the following. I don't think
that just because that it has a BUGS section in the manpage, it can be
called broken. man bash also has BUGS section, is bash considered as
broken?

BUGS
   getopt(3) can parse long options with optional arguments that
are given an empty optional argument (but can not do this for short
options). This  getopt(1)  treats
   optional arguments that are empty as if they were not present.

   The syntax if you do not want any short option variables at all
is not very intuitive (you have to set them explicitely to the empty
string).

AUTHOR
   Frodo Looijaard 


Note that it doesn't mean that I am resistant to getopts. It is just
that I don't think that your logic is valid. But I will read more
about getopts to see if it is necessary to convert from getopt to
getopts.

> ./myscript . -type f -name '*'

To support your claim, tell me what myscript would be if the commands

./myscript 'a b' 'c d' -type f -name '*"
./myscript 'a b' -type f -name '*"

actually do

find 'a b' 'a d' -maxdepth 1 -type f -name '*"
find 'a b' -maxdepth 1 -type f -name '*"

-- 
Regards,
Peng



Re: converting array to string by quoting each element for eval

2011-11-16 Thread Greg Wooledge
On Wed, Nov 16, 2011 at 08:05:03AM -0600, Peng Yu wrote:
> > **NEVER** use getopt(1).  It is broken.  It cannot be made to work
> > correctly.  Its entire design is flawed.
> 
> I don't see these warnings in my systems (macports and ubuntu)

Debian getopt(1) says:

   Traditional implementations of getopt(1) are unable to cope with white-
   space and other (shell-specific) special characters  in  arguments  and
   non-option  parameters.  To solve this problem, this implementation can
   generate quoted output which must once  again  be  interpreted  by  the
   shell  (usually by using the eval command). This has the effect of pre-
   serving those characters, but you must call getopt in a way that is  no
   longer  compatible  with  other versions (the second or third format in
   the SYNOPSIS).  To determine whether this enhanced version of getopt(1)
   is installed, a special test option (-T) can be used.

And that is enough of this nonsense.  I have cited three official manuals
for you already.  Let's move on.


> To support your claim, tell me what myscript would be if the commands
> 
> ./myscript 'a b' 'c d' -type f -name '*"
> ./myscript 'a b' -type f -name '*"
> 
> actually do
> 
> find 'a b' 'a d' -maxdepth 1 -type f -name '*"
> find 'a b' -maxdepth 1 -type f -name '*"

You have a double-quote at the end of each line.  I will assume this is
a typo which was cut-and-pasted several times, and that you actually want
this invocation:

  ./myscript 'a b' 'c d' -type f -name '*'

to have this effect:

  find 'a b' 'a d' -maxdepth 1 -type f -name '*'

Or in other words, you want to write a wrapper script which accepts
find(1) arguments but inserts the arguments -maxdepth 1 after the last
pathname.

Now that we know the goal, it's simple enough:

#!/bin/bash
paths=() i=0
while [[ $1 != -* ]]; do
  paths[i++]=$1; shift
done
exec find "${paths[@]}" -maxdepth 1 "$@"


For testing purposes, I will replace "find" with "args", which is a
script I use to dump arguments to stdout so I can see them.

imadev:~$ ./foo 'a b' 'c d' -type f -name '*'
8 args:   <-maxdepth> <1> <-type>  <-name> <*>

This appears to work correctly, assuming I understand what your goal is.

Here is ~/bin/args:

#! /bin/sh
printf "%d args:" $#
printf " <%s>" "$@"
echo



Re: converting array to string by quoting each element for eval

2011-11-16 Thread Peng Yu
> And that is enough of this nonsense.  I have cited three official manuals
> for you already.  Let's move on.

I don't get it. Do you mean both traditional getopt and Debian getopt
are broken. To me it seems that Debian getopt is made to address the
short coming of transitional getopt. Yet you still think Debian getopt
is broken?

> Now that we know the goal, it's simple enough:

No. That is not my goal. It is just a simplification of my goal. It is
really hard to enumerate all the possible use cases, but I will try.

In additional to the use cases I stated in the previous email, let's
consider some more:

 ./myscript 'a b' 'c d' -o output.txt -type f -name '*'

or

 ./myscript 'a b' 'c d' -output output.txt -type f -name '*'

or

 ./myscript -output output.txt -type f -name '*' 'a b' 'c d'

or

 ./myscript -type f -name '*' 'a b' -output output.txt  'c d'

is equivalent

 find 'a b' 'a d' -maxdepth 1 -type f -name '*' > output.txt


-- 
Regards,
Peng



Re: converting array to string by quoting each element for eval

2011-11-16 Thread Peng Yu
> You may safely use getopts (the builtin).  Never getopt.

If my understanding is correct, 'getopts' doesn't support the long
format. Hence, it does not satisfy my need and I shall not use it.

-- 
Regards,
Peng