18

Okay, I can display an environmental variable from the commandline:

echo $COLUMNS

And get a response.

But I can't execute that from within a shell script, I get nothing. So, there must be a way to import that environment variable - but I've not been able to find a simple solution/explanation.

Once upon a time I recall seeing something like $ENV_COLUMNS, but that's not correct (or is missing something).

I'm trying for something like this:

    for x in $COLUMNS
     do echo -n "-"
    done
    echo #to get the /n
Evgeny
  • 5,476
user3082
  • 991
  • 2
  • 10
  • 18
  • all shell scripts will understand the environment variables by default.... which shell are you using to run this? go and set env in the corresponding rc file –  Jul 13 '15 at 06:35
  • @anon3202, please join this site and post as a registered user to make the discussion more fruitful. I've just mistenkenly rejected an anonymous edit probably from you... – yaegashi Jul 13 '15 at 07:57

7 Answers7

12

You should do:

COLUMNS=$COLUMNS my_script

You could also do something like this rewrite in sed:

 STTY=
 for fd in 0 1 2
 do      [ -t "$fd" ]    &&
         break
 done|| ${STTY:?Run "$0" on a terminal}
 STTY=$( stty -a <&"$fd" |
         sed     -Ee'/;/{s/^/;/' \
                 -e's/((; *[^ ;]* )[= ]*)?([^;])/\2\\\3/g' \
                 -e's/; *([^ ;]+) ([^;]*)/\n\1=\2/g' \
                 -e's/;* *$//;t' -e\} \
                 -e'H;$!d;x;s/[[:space:]]+/,/g' \
                 -e's/^,*/FLAGS=/;s/,*$//')

On my machine (on this terminal) that puts the following value in $STTY:

speed=\3\8\4\0\0\ \b\a\u\d
rows=\4\3
columns=\1\0\9
line=\0

intr=\^\C
quit=\^\\
erase=\^\H
kill=\^\U
eof=\^\D
eol=\<\u\n\d\e\f\>

eol2=\<\u\n\d\e\f\>
swtch=\<\u\n\d\e\f\>
start=\^\Q
stop=\^\S
susp=\^\Z
rprnt=\^\R

werase=\^\W
lnext=\^\V
discard=\^\O
min=\1
time=\0
FLAGS=-parenb,-parodd,-cmspar,cs8,-hupcl,-cstopb,cread,-clocal,-crtscts,-ignbrk,-brkint,-ignpar,-parmrk,-inpck,-istrip,-inlcr,-igncr,icrnl,ixon,-ixoff,-iuclc,-ixany,-imaxbel,iutf8,opost,-olcuc,-ocrnl,onlcr,-onocr,-onlret,-ofill,-ofdel,nl0,cr0,tab0,bs0,vt0,ff0,isig,icanon,iexten,echo,echoe,echok,-echonl,-noflsh,-xcase,-tostop,-echoprt,echoctl,echoke,-extproc

...which should be plenty safe for eval, but it may be a little over the top, though.

mikeserv
  • 58,310
7

You might try to

export COLUMNS

See this for an explanation.

But you should tell us how is the script called. If it is started by some crontab, it is likely to be executed in an environment without COLUMNS. You might use printenv to check.

6

This is a follow-on to your previous question and we're getting to what it is you want to do. I'm quite sure others have their own styles for this, but perhaps this will get you started.

#!/bin/bash
SCREEN_WIDTH=$(stty size | awk '{print $2}')
echo "$SCREEN_WIDTH"

That echo isn't what you are trying to do, just to demonstrate we've put the value somewhere readily accessible.

ilkkachu
  • 138,973
Jason
  • 191
3

An environment variable is passed to a script. The problem is that COLUMNS is not an environment variable.

From a script, you can call a command such as tput to retrieve the terminal dimensions.

width=$(tput cols)
</dev/zero head -c "$width" | tr '\0' '-'; echo

(This script may not be portable beyond Linux.)

1

So, it appears that COLUMNS is not in env, so I guess the title of this thread is incorrect, as it's not an environment variable?

   export COLUMNS
   echo $COLUMNS

Does not work. From the link I gather export is to make something available from the parent process to a child process, which is not what I want to do. Not sure what that suggestion was about, or if I'm misreading/misunderstanding what was being suggested.

COLUMNS=$COLUMNS my_script

Results in:

   fork: retry: No child processes
   fork: Resource temporarily unavailable

And I've not worked my way through the rest of that "over the top" suggestion, as it's about as clear as mud.

   screen_width=`stty size | cut -f2 -d " " -`

Is working, however. But that only solves the proximate problem, not the actual problem, as there are more things in set that I might want to get out - and I don't know the commands for each of them (if they have commands). Using cut instead of awk / sed / whatever, as I'd like something that's as portable as possible (and I don't know if stty is portable, but it's working right now, so I'm crossing my fingers).

I am using a while loop, yeah the for loop didn't work out the way I imagined it would, and no seq modifier/whatever in my shell.

I'd really like to know why I need double parens, but need them I do.

This "go and set env in the corresponding rc file", sounds interesting, but the directions are unclear :) I'm guessing that means I could add particular variables to the list that env pulls up?

user3082
  • 991
  • 2
  • 10
  • 18
1

Here's a 30-second example:

  1. Create a file called test.sh
  2. Place this inside it
#!/bin/bash
echo $thing
  1. Run this to make it excitable chmod +x test.sh
  2. Run the script (you won't see any output, since $thing has no value (yet)
./test.sh
  1. Now give it an environment variable and run it again, this time you'll see output
thing=something-random ./test.sh
something-random
stevec
  • 181
0

Not an direct answer to your question, but ... why don't you pass that as an argument to your script?

your_script $COLUMNS

where your_script would contain code like

while (( $# ))
do
    echo -n "-"
    shift
done
echo

EDIT: After reading Jason's answer, I checked COLUMNS value (it is a single value), and in my case seen it is 80, then realize your for loop is wrong (my previous script was for a multi-value variable, not a single value variable). Your for loop will only run once, if you want to run a for loop four times, then you should:

for i in 1 2 3 4
do
   your stuff here
done

But in your case I guess that what you want is something like:

count=$1
while (( $count ))
do
    echo -n "-"
    count=$(($count-1))
done
AdminBee
  • 22,803
YoMismo
  • 4,015