Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

Normally, bash is able to assign multi-line output of a command:

L=`ls`

This works from both interactive shell and scripts. But it appears the output of a builtin can't be captured in a variable:

L=`dirs -l -p`

This works in the interactive shell, but in the script only first line end up in the variable, probably due to different treatment of builtins by bash.

Why does it happen, and how can I do what I need?

share|improve this question
    
dirs -l -p gives me /home/phunehehe, and running L=`dirs -l -p`; echo $L always gives me /home/phunehehe. Why are you using it to test "multiline output"? –  phunehehe Sep 7 '10 at 2:23
1  
@phunehehe, sorry, you have to push (pushd <dir>) some directories on the stack to have more than one line. –  Alex B Sep 7 '10 at 3:38
    
Is it the dirs command that you specifically need in your script? If so, you'll need to better explain what you need as dirs (and $DIRSTACK) are treated specially in non-interactive shells. Bash in general tries to make built-ins behave like external commands, except in cases where there is affirmative reason not to. –  msw Sep 7 '10 at 3:43
    
Autojump may do what you need or at least have ideas worth stealing: github.com/joelthelion/autojump/wiki –  msw Sep 7 '10 at 3:48
    
@msw I specifically need dirs output, since I am writing a bash function to cd based on regex (since I am already using pushd/popd, I'd like to keep it integrated with directory stack). But I think your remark warrants a separate answer if you can explain why bash treats dirs differently. –  Alex B Sep 7 '10 at 3:52
show 2 more comments

2 Answers

up vote 5 down vote accepted

There seems to be some ambiguity in the way that you worded your question. You said:

but in the script only first line end up in the variable

and then your comments suggest that you are writing a shell function - not a script.

I suspect you know that scripts are useless for changing directories, since any cd within a script does not propagate out to the superior shell. If indeed you are trying to develop your directory changer in a script, you'll have a tough time as the directory stack is not inherited by subordinate shells:

$ dirs -l
/home/msw /home/msw/Ubuntu One /home/msw /usr/bin /usr/local /bin /usr/local
$ cat > dirs.sh
dirs -l 
$ bash dirs.sh
/home/msw

You could get a function to help out:

$ function passdirs() { bash ndirs.sh `dirs -l -p`; }
$ cat > ndirs.sh
echo $#
echo "$@"
$ passdirs
8
/home/msw /usr/local /usr/bin /bin /usr/local /usr/bin /bin /home/msw

but, of course you'd need the function to also effect the cd in the current shell in which case wrapping and unwrapping arguments through the command line is a quoting chore so you are best just doing it all in the function

$ function cd_pattern() {
   cd $(dirs -l -p | grep --max-count=1 -e "$1") ; dirs
}
$ dirs
~ /usr/local /bin /usr/share/doc/evince ~/Ubuntu One
$ cd_pattern v..c
/usr/share/doc/evince /usr/local /bin /usr/share/doc/evince ~/Ubuntu One

which also switched to using $(...) as a synonym for backticks to reduce quoting confusion.

share|improve this answer
    
Bah, of course! I was writing a function for ~/.bashrc, but was testing it... drum roll... in a script. –  Alex B Sep 7 '10 at 5:46
add comment

The output of commands can vary depending on whether it is run interactively or within a script. For example, "multiline output" goes fine with export:

#! /bin/bash
L=`export`
echo "$L"

, which gives you all the output just the same as when you run it interactively.

But not alias, which gives you nothing.

share|improve this answer
1  
Aliases are intentionally disabled in non-interactive scripts: "aliases are not expanded when the shell is not interactive, unless the expand_aliases shell option is set". Which you should probably never do as it would be a great vector for exploits. –  msw Sep 7 '10 at 3:31
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.