Re: trap output piped to another program gives incomplete results

2010-03-31 Thread Eric Blake
On 03/30/2010 11:45 PM, Siddhesh Poyarekar wrote:
> Fix:
> 
>   I've not looked at how this can be fixed yet, but it looks
>   like bash is forking for the trap builtin, which inherits the
>   ignored signals, hence showing only them as active traps
>   into the pipe. The other signals are not inherited and hence
>   do not show up at all.

See also this Austin Group report:
http://austingroupbugs.net/view.php?id=53

which states this about running trap in a subshell:

Change

"When a subshell is entered, traps that are not being ignored are
set to the default actions."

to

"When a subshell is entered, traps that are not being ignored shall
be set to the default actions, except in the case of a command
substitution containing only a single trap command, when the traps
need not be altered. Implementations may check for this case
using only lexical analysis; for example if `trap` and $( trap -- )
do not alter the traps in the subshell, cases such as assigning
var=trap and then using $($var) may still alter them."

Change

"The trap command with no arguments shall write to standard output
a list of commands associated with each condition."

to

"The trap command with no operands shall write to standard output
a list of commands associated with each condition. If the command
is executed in a subshell, the implementation does not perform
the optional check described above for a command substitution
containing only a single trap command, and no trap commands with
operands have been executed since entry to the subshell, the list
shall contain the commands that were associated with each
condition immediately before the subshell environment was entered.
Otherwise, the list shall contain the commands currently
associated with each condition."

-- 
Eric Blake   ebl...@redhat.com+1-801-349-2682
Libvirt virtualization library http://libvirt.org



signature.asc
Description: OpenPGP digital signature


Strings manipulation without using variables

2010-03-31 Thread Francesco Pretto
Hello,

I'm sorry if this isn't the wrong place to ask, but I couldn't find an user
mailing list. My question is if it's possible to manipulate strings without
using  variables. Or, how to do the following in one line without using a
variable:

FILENAME=$(ls | tail --lines=1)
echo ${FILENAME%.*}

I searched a lot and, surprisingly, I couldn't find any other syntax.

Thanks,
Francesco





Re: Strings manipulation without using variables

2010-03-31 Thread Bob Proulx
Francesco Pretto wrote:
> I'm sorry if this isn't the wrong place to ask, but I couldn't find an user
> mailing list.

The help-gnu-ut...@gnu.org mailing list is available for generic help
questions such as this.

> My question is if it's possible to manipulate strings without
> using  variables. Or, how to do the following in one line without using a
> variable:

The shell itself needs a variable to perform the replacement
operation.  But you don't need to structure your task that way.

> FILENAME=$(ls | tail --lines=1)

Note that your locale setting (LANG, LC_ALL) affects sort ordering.

> echo ${FILENAME%.*}

Since you already have a pipeline you could do this:

  FILENAME=$(ls | tail --lines=1 | sed 's/\.[^.][^.]*$//')

Or with GNU sed using the \+ extension:

  FILENAME=$(ls | tail --lines=1 | sed 's/\.[^.]\+$//')

I assume that 'ls' isn't what you actually are doing, that you have
reduced the test case to something smaller (thank you for that!)
because the shell can list the directory itself.

  for f in *;do FILENAME=$f; done
  ( Or even: for FILENAME in *;do : ; done )

And you could then slip in your variable manipulation right there.

  for f in *;do FILENAME=${f%.*}; done
  echo $FILENAME

Bob




Re: Strings manipulation without using variables

2010-03-31 Thread Greg Wooledge
On Wed, Mar 31, 2010 at 11:03:17AM -0600, Bob Proulx wrote:
> Or with GNU sed using the \+ extension:
> 
>   FILENAME=$(ls | tail --lines=1 | sed 's/\.[^.]\+$//')
> 
> I assume that 'ls' isn't what you actually are doing, that you have
> reduced the test case to something smaller (thank you for that!)
> because the shell can list the directory itself.

Such optimism.

Just in case, it needs to be pointed out that using ls in this way is
NOT a safe operation, since filenames may contain newlines (or other
characters that ls may choose to represent with a ? instead of leaving
intact, depending on the implementation).  Newlines will completely
break any line-based approach, and characters that are munged into ?
will break anything that relies on the output of ls for that filename.

>   for f in *;do FILENAME=$f; done
>   ( Or even: for FILENAME in *;do : ; done )
> 
> And you could then slip in your variable manipulation right there.
> 
>   for f in *;do FILENAME=${f%.*}; done
>   echo $FILENAME

echo "$FILENAME" of course; or printf "%s\n" "$FILENAME" for 100% safety.

The approach that immediately sprang to mind for me was to use an array:

   files=(*); lastfile=${fil...@]:(-1)}; lastfile=${lastfile%.*}

That uses more memory, as it stores all the filenames.  But if you need
more than just the one filename, it may pay off.