How can I redirect stdout to a variable

I can store the stdout from a shell command by redirecting it to a file. For example I can store the partition structure in data.txt like this:

fdsik -l > data.txt

But I don’t want to store that on disk. Is there a way to define a file in RAM and store it there for a while? Or is htere a way to store it in an environment variable for a while?

You can store it into a (environment) variable with:

var="$(fdisk -l)"

or using old style shell backtick syntax for portability:

var="`fdisk-l`"

However this variable is only available to the current shell. If it’s an environment variable, you can export it to descendant shells:

export VAR="$(fdisk -l)"

or

VAR="`fdisk -l`"
export VAR

If you want it to hang around for a while, you’ll have to use a file.

Thanks ken_yap. Works a treat.

Is there a way to keep the CR/LF stuff in, or grep the data into individual lines, or replace CR/LFs with another character so I can later parse them in a language that’s a derivative of c. Currently I get it in an unbroken string and I want to ingest the $var into a program using c’s environment variable ability, parse it and use it to paint a GUI of the partitions. Ordinarily a storage file would be OK, but I want to do this on a live CD (which is another issue as you know).

On Unix it’s only LF, no CR.

You have to realise that the loss of the LF is at the expansion stage. Try this:


a=$(echo -e "a
b")
echo "$a" | od -bc

OK thanks – nearly got it.
I have a book “From Bash to Z shell”. It’s time to read it and follow the examples.

The thing I’ve learned is that “Yes” it’s possible to define an environment variable and use it to get info into the program that interrogated the system it is running in.

OK progress in leaps and bounds:
I got to thinking about that stuff and pipes – must be much the same thing as a pipe – so:
This code reads stuff in line by line through a pipe that preserves the lines beautifully for parsing:

Dim as string cmd, txt(1000)
Dim as Integer i
cmd = "fdisk -l"

Open Pipe cmd For Input As #1
Print "Output of", cmd

i = 0
Do While Not EOF(1)
i = i + 1
Line Input #1, txt(i)
Print txt(i)
Loop

Close #1
End

And it runs nicely, printing out the variable txt(i) line by line as a faithful reproduction of the fdisk command. So thanks ken_yap for the ideas.

Or in Perl:

#!/usr/bin/perl -w
open(P, "fdisk -l |") or die;
while (<P>) {
  print $_;
}

Now this is a quicky because I am almost gone for a few weeks. And I am not sure if you are now after saving in a variable or interpreting the output in a script. I always do interpreting in a shell in this form:

fdisk -l | while read LINE
do      ; # the parsing of a line
done

or when you e.g. want only to interprete the lines with the partitions:

fdisk -l | grep '^/' | while read DEV T1 T2 T3 T4 T5 T6
do      ; # remember that sometimes T1 is a *, but mostly it is the start 
done

Hope this helps. And now: OFF I go!

On Tue, 22 Jul 2008 13:56:04 GMT
ken yap <ken_yap@no-mx.forums.opensuse.org> wrote:

>
> Or in Perl:
>
>
> Code:
> --------------------
> #!/usr/bin/perl -w
> open(P, “fdisk -l |”) or die;
> while (<P>) {
> print $_;
> }
> --------------------
>
>
A bit longer code, but if you need access to the data later, don’t
untie the array.

#!/usr/bin/perl

***** Define PERL functions *****

use warnings;

Access the lines of a file via an array

use Tie::File;

Set Access Control

use Fcntl ‘O_RDWR’, ‘O_RDONLY’;

***** Define global variables *****

my $file = “/tmp/fdisk_out”;
my $count = 0;
my $line = 0;

Create fdisk listing

/sbin/fdisk -l > $file;

Tie $file

tie @fdiskdata, ‘Tie::File’, “$file” , mode => O_RDWR or die;
foreach $line (@fdiskdata) {
$count ++;
print "$count. $fdiskdata$count-1]
";
}
untie @fdiskdata;


Cheers Malcolm °¿° (Linux Counter #276890)
SLED 10 SP2 i586 Kernel 2.6.16.60-0.25-default
up 4:51, 2 users, load average: 0.12, 0.11, 0.18
GPU GeForce Go 6600 TE/6200 TE Version: 173.14.09

You guys are so good – thanks for the tips.

Four of the things I like about my clumsy, old fashioned code are:

it compiles into a c executable (very portable)
it speaks in long-winded fashion (easy debugging)
it has string handling (up there with PHP)
it has great intrinsic graphics

and with pipes I can get to and from the OS almost as easily as a script does.

I tried a bit of conceptualising in PHP, running stuff in a web browser which is one of the ways of the future, and that’s very promising, so Perl, which is much the same in power as PHP, would be great too, but I want a portable product one day.

And those tips you guys gave are eye openers.

All,

I’m trying the same thing, more or less but in BASH and need to parse from “fdisk -l | grep -i disk | grep -i dev”:

 Results: Disk /dev/sde: 63.2 GB, 63216549888 bytes 

the “sde” (column 2) and the size “63.2 GB” (column 3).

Then need to parse from running “df -h”:

 Results: /dev/sdc1        59G   11M   59G   1% /media/sdc1 

column #4 "Available space and column #6 the mount point.

NOTE: I ran these back to back on my machine and notice “fdisk -l” says the drive is on sde1 and “df -h” says it is on sdc1. These have to match as I want the “df -h” to actually be “df -h | grep -i ${SDDRV}” where ${SDDRV} is the derived drive denoter from column 2 of the fdisk command. If I run “df -h | grep -i sde” using the current value from “fdisk -l” then I get nothing.

Idea is to export a var containing for any/all attached USB Flash drives 1.) Drive size, 2.) Available size, 3.) Mount point.

I have a script underway, for mounting the drive, that I posted via pastebin at:

http://pastebin.com/PUrSra8m

But need to finish out by making the “hardcoded” line work to search for all mounted drives and all target backup dirs (?? from passed parm ?? was not sure which direction to go with this, so hardcoded what I needed to get it working NOW!)

Hope all you can help me interpret to BASH, eliminate the “fdisk” to “df” drive error and show me some parsing techniques to get the right info!

Cheers!

OMR

On 2014-06-04 20:26, OldManRiver wrote:
>
> All,
>
> I’m trying the same thing, more or less but in BASH and need to parse
> from “fdisk -l | grep -i disk | grep -i dev”:


#!/bin/bash
TEXT=`fdisk -l | grep -i disk | grep -i dev`
echo "----------------------"
echo "$TEXT"

works here.


Cheers / Saludos,

Carlos E. R.
(from 13.1 x86_64 “Bottle” at Telcontar)

Use ERE in grep.

fdisk -l | grep -Ei 'disk.*dev'

Also if you want to see the usb disk it will require you to run this as root.

command -p grep -Ff <(hwinfo --disk --short) <(hwinfo --usb --short)

or If you have labeled your disk.

blkid

Well perhaps you can paste a sample input and output of what you want and not paste the magic code :).
Any ways if not me then someone can answer you for sure.

Parsing **fdisk -l **This should store the output in the variable foo

foo=$(
  regex=Disk.*dev 
  while IFS=:, read -ra line; do 
     $line =~ $regex ]] && echo "${line[0]#* }" "${line[1]}"
  done < <(fdisk -l)
)

Parsing the output of df -h this should store the output in the variable bar.

bar=$(
   while read -ra line; do 
      $line = /dev* ]] && echo "${line[3]}" "${line[5]}"
   done < <(df -h)
)

since grep is line based, it is not suitable for the task imo. Also awk can do that much better and python and perl and ruby and …
but hey why involve some external commands and other tools if the shell can do what you want, right?:slight_smile: