0

I am having trouble writing a bash script that saves each line of the output from the command #mount | grep ^\/dev/ into a variable.

Below is my bash script.

#!/bin/bash
mount | grep ^\/dev/ > tempoary
input=$(cat tempoary)
x=0
while IFS= read -r line
do
  x=$((x+1))
  echo "$line" > /tmp/directory/$x
  for file in $(echo "$line"); do
  eval "var$x=$file";
  echo "$file"
  done
done <<< "$input"

Output below:

[root@localhost tmp]# sh script
/dev/mapper/rhel-root
on
/
type
xfs
(rw,relatime,seclabel,attr2,inode64,noquota)
/dev/sda1
on
/boot
type
xfs
(rw,relatime,seclabel,attr2,inode64,noquota)

I expect to have output format like this:

[root@localhost tmp]# sh script
/dev/mapper/rhel-root on / type xfs (rw,relatime,seclabel,attr2,inode64,noquota)
/dev/sda1 on /boot type xfs (rw,relatime,seclabel,attr2,inode64,noquota)

Can you give me some pointers to how I can achieve this?

PS. Double quoting "$(echo "$line")" won't help, it would only prompt syntax error below.

[root@localhost tmp]# sh script
script: eval: line 14: syntax error near unexpected token `('
script: eval: line 14: `var1=/dev/mapper/rhel-root on / type xfs (rw,relatime,seclabel,attr2,inode64,noquota)'
2
  • Clearly mount | grep ^\/dev/ will give the sort of output you want. So all this processing is for some other reason. What is it you're trying to do? After all, mount | grep ^\/dev/ | while read -r line; do echo "$line"; done is a simple loop that displays the same thing. Jul 6, 2020 at 2:46
  • I am trying to save the outputs of the "mount | grep ^\/dev/" into variables within shell script, that can be used to further process if it includes certain string within the variable. So for example, the outputs are "/dev/mapper/rhel-root on / type xfs (rw,relatime,seclabel,attr2,inode64,noquota)" and "/dev/sda1 on /boot type xfs (rw,relatime,seclabel,attr2,inode64,noquota)" respectively. After saving these 2 lines into variable1 and variable2 in the bash, I would like to further process using if-then-else statement to process if they include string "noexec" within brackets, which is no.
    – Leon
    Jul 6, 2020 at 7:59

3 Answers 3

1

Redirect the file directly to while ... done:

mount | grep ^\/dev/ > tempoary
while IFS= read -r line
do
...
done < temporary

or use process substiution to omit the temporary file:

while IFS= read -r line
do
...
done < <(mount | grep ^\/dev/)

or similarly pipe to while

mount | grep ^\/dev/ |
while IFS= read -r line
do
...
done
3
  • why not mount | grep ^\/dev/ | while IFS= read -r line ?
    – Archemar
    Jul 6, 2020 at 8:01
  • sure, that works, I just prefer done < <(cmd) for readability and habit, but it's simply a matter of choice :-)
    – pLumo
    Jul 6, 2020 at 8:03
  • if instructions within do .. done span too many lines, I feel loop harder to read as I don't know what is fed to loop, if command or file is before I find it easier.
    – Archemar
    Jul 6, 2020 at 8:05
0

Adding IFS before for loop and quoting the file variable make things working all fine... Check this out:

#!/bin/bash
mount | grep ^\/dev/ > tempoary
input=$(cat tempoary)
x=0
while IFS= read -r line
do
  x=$((x+1))
  echo "$line" > /tmp/tmp/$x
  IFS=
  for file in $(echo "$line"); do
  eval "var$x='$file'";
  echo "$file"
  done
done <<< "$input"
0

Based on the comment

the outputs are "/dev/mapper/rhel-root on / type xfs (rw,relatime,seclabel,attr2,inode64,noquota)" and "/dev/sda1 on /boot type xfs (rw,relatime,seclabel,attr2,inode64,noquota)" respectively. After saving these 2 lines into variable1 and variable2

Standard variables aren't necessarily the best answer. Instead an array is more likely to be what you want.

For example:

#!/bin/bash

typeset -A mounts

let index=0

m=$(mount | grep "^/dev/")

while read line
do
  mounts[$index]="$line"
  let index=index+1
done <<< "$m"

echo There were $index lines
let a=0
while [ $a -lt $index ]
do
  echo Line $a was ${mounts[$a]}
  let a=a+1
done

On my machine, if I run this I get

There were 4 lines
Line 0 was /dev/vda3 on / type ext4 (rw,relatime,data=ordered)
Line 1 was /dev/vda1 on /boot type ext4 (rw,relatime,data=ordered)
Line 2 was /dev/vdb on /news type ext3 (rw,relatime,data=ordered)
Line 3 was /dev/vdc1 on /brick type ext3 (rw,relatime,data=ordered)

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .