[Top][All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: bash: request for a way to return variables to the parent of a subsh

From: Richard Neill
Subject: Re: bash: request for a way to return variables to the parent of a subshell
Date: Wed, 23 Jul 2008 05:01:21 +0100
User-agent: Thunderbird (X11/20080629)

Dear Eric,

Thank you for your helpful answer. I'd understood that bash *doesn't* pass info back from the child to the parent, but I didn't realise that it was fundamentally *impossible* to do in Unix. I guess that tempfiles would do it - though that's rather ugly.

Is there any way to use "read" to iterate over its standard input without creating a subshell? If it's of interest, the actual part of the script I use is below - the aim is to parse the output of "ffmpeg -formats" to see whether certain codecs are supported by that build.




#Does this version of FFMPEG support the relevant file format?  Exit
#if not. Arguments:  $1='file' or 'codec';  $2='E','encode' or
# 'D','decode', $3=format/codec_name
#Example:    check_ffmpeg_format file D ogg

#The output of `ffmpeg -formats`  has section headings such as
#"File formats", and each section is delimited by a blank line.

#The first part of the line contains letters DEA(etc) depending
#on whether the codec/file is supported
#for reading (decoding) and/or writing (encoding).

function check_ffmpeg_format_support(){                         .
    local filecodec=$1
    local decodeencode=$2
    local filecodec_name=$3

    if [ $filecodec == 'file' ];then
        local start_trigger='File formats:'
        local end_trigger=''
        local terminator='\ +'
        local filecodec_txt='file format'
        local start_trigger='Codecs:'
        local end_trigger=''
        local terminator='$'
        local filecodec_txt='with codec'

    if [ $decodeencode == 'decode' -o $decodeencode == 'D' ];then       
        local decodeencode='D[A-Z ]*'
        local decodeencode_txt='decoding'
        local decodeencode='[A-Z ]?E[A-Z ]*'
        local decodeencode_txt='encoding'

  local matchme='^\ *'$decodeencode'\ +'$filecodec_name'\ *'$terminator
    local relevant=false

#Warning: this pipe has the effect of a subshell. Variables are
#set inside the pipeline, and cannot be accessed outside it.
#Search between trigger points.

    ffmpeg -formats 2>/dev/null | while read line ; do
        if [[ $line =~ $start_trigger ]]; then
        if [[ $line == $end_trigger ]]; then
        if [ "$relevant" == true ];then
            if [[ $line =~ $matchme ]];then     #Regex match.
                exit 2                          
            #Exit the '| while read...'  part, and return $? so we
            #know the result.

    if [ $? != 2 ]; then
        echo -e "ERROR: the installed version of 'ffmpeg' was built
        without support enabled for $decodeencode_txt $filecodec_txt
         exit 1


Eric Blake wrote:
According to Richard Neill on 7/22/2008 8:04 PM:
| This prints "Match-1", but does not print "Match-2".
| The only way to get data out of the read-subshell is by something like
| "exit 2", and looking at $?

You can also use files.  The position within a seekable file is preserved
from child to parent, but once you are using files, you might as well go
with the file contents.

| It's already possible to export a variable into the environment, and for
| subshells to inherit variables from the main script. Do we need a new
| keyword to achieve the reverse? Is there any way to make sure that
| variables defined at [a] can be made to still exist at [b] ?

A new keyword is insufficient.  This is something that is fundamentally
not provided by Unix systems - short of using the file system, there
really isn't a way to pass arbitrary information from a child process back
to the parent.

But maybe the 'source' builtin is what you are looking for, to execute a
script in the same context rather than forking off a child.

reply via email to

[Prev in Thread] Current Thread [Next in Thread]