Reads from the file descriptor (fd)

From Linux Shell Scripting Tutorial - A Beginner's handbook
Jump to: navigation, search
← Opening the file descriptors for reading and writingHomeExecutes commands and send output to the file descriptor (fd) →

You can use the read command to read data from the keyboard or file. You can pass the -u option to the read command from file descriptor instead of the keyboard. This is useful to read file line by line or one word at a time.

Syntax

read -u fd var1 var2 ... varN

OR use the while loop to read the entire file line:

           while IFS= read -u fd -r line
           do
                 command1 on $line
                 command2 on $line
                 ..
                 ....
                 commandN
           done

Example

Create a shell script called readwritefd.sh as follows:

#!/bin/bash
# Let us assign the file descriptor to file for input fd # 3 is Input file 
exec 3< /etc/resolv.conf
 
# Let us assign the file descriptor to file for output fd # 3 is Input file 
exec 4> /tmp/output.txt
 
# Use read command to read first line of the file using fd # 3
read -u 3 a b
 
# Display data on screen
echo "Data read from fd # 3:"
echo $a $b
 
# Write the same data to fd # 4 i.e. our output file
echo "Writing data read from fd #3 to fd#4 ... "
echo  "Field #1 - $a " >&4
echo  "Field #2 - $b " >&4
 
# Close fd # 3 and # 4
exec 3<&-
exec 4<&-

Save and close the file. Run it as follows:

chmod +x readwritefd.sh
./readwritefd.sh

Sample output:

Data read from fd # 3:
nameserver 192.168.1.254
Wrting data read from fd #3 to fd#4 ... 

To view data written to fd # 4 i.e. /tmp/output.txt, use the cat command as follows:

cat /tmp/output.txt

Sample outputs:

Field #1 - nameserver 
Field #2 - 192.168.1.254

Shell Script To Display Its Own FDs

The following shell script displays its actual fd numbers and file associated with them (displayfds.sh):

#!/bin/bash
# Let us assign the file descriptor to file for input fd # 3 is Input file 
exec 3< /etc/resolv.conf
 
# Let us assign the file descriptor to file for output fd # 3 is Input file 
exec 4> /tmp/output.txt
 
# Use read command to read first line of the file
read -u 3 a b
 
echo "*** My pid is $$"
mypid=$$
 
echo "*** Currently open files by $0 scripts.."
 
ls -l /proc/$mypid/fd
 
# Close fd # 3 and # 4
exec 3<&-
exec 4>&-

Save and close the file. Run it as follows:

chmod +x displayfds.sh
./displayfds.sh

Sample output:

*** My pid is 19560
*** Currently open files by ./displayfds.sh scripts..
total 0
lrwx------ 1 vivek vivek 64 2009-09-20 01:45 0 -> /dev/pts/2
lrwx------ 1 vivek vivek 64 2009-09-20 01:45 1 -> /dev/pts/2
lrwx------ 1 vivek vivek 64 2009-09-20 01:45 2 -> /dev/pts/2
lr-x------ 1 vivek vivek 64 2009-09-20 01:45 255 -> /tmp/displayfds.sh
lr-x------ 1 vivek vivek 64 2009-09-20 01:45 3 -> /etc/resolv.conf
l-wx------ 1 vivek vivek 64 2009-09-20 01:45 4 -> /tmp/output.txt
  1. The file descriptors 3 is assigned to /etc/resolv.conf and 4 is assinged to /tmp/output.txt.
  2. Fd # 0, 1, and 2 are all assinged to /dev/pts/2 i.e. my screen in this output.
  3. The ls /proc/$mypid/fd command lists all open fds using scripts PID (process identification number) number.
  4. The proc file system (/proc) is a pseudo-file system which is used as an interface to kernel data structures.
  5. There is a numerical subdirectory for each running process; the subdirectory is named by the process ID. Each such subdirectory contains the pseudo-files and directories.
  6. /proc/[PID]/fd is one of such directory containing one entry for each file which the process has open, named by its file descriptor, and which is a symbolic link to the actual file. Thus, 0 is standard input, 1 standard output, 2 standard error, 3 /etc/resolv.conf, 4 /tmp/output.txt etc.

Shell Script To Read File Line by Line

Create a shell script called readfile.sh:

#!/bin/bash
# Shell script utility to read a file line line.
FILE="$1"
 
# make sure filename supplied at a shell prompt else die
[ $# -eq 0 ] && { echo "Usage: $0 filename"; exit 1; } 
 
# make sure file exist else die
[ ! -f $FILE ] && { echo "Error - File $FILE does not exists." ; exit 2; }
 
# make sure file readonly else die
[ ! -r $FILE ] && { echo "Error - Can not read $FILE file."; exit 3; }
 
IFS=$(echo -en "\n\b")
 
exec 3<$FILE
while read -u 3 -r line
do
	echo $line
done
 
# Close fd # 3
exec 3<&-
 
# exit with 0 success status 
exit 0

Save and close the file. Run it as follows:

chmod +x readfile.sh
./readfile.sh /etc/resolv.conf
← Opening the file descriptors for reading and writingHomeExecutes commands and send output to the file descriptor (fd) →