Reads from the file descriptor (fd)
From Linux Shell Scripting Tutorial - A Beginner's handbook
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.
Contents |
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
- The file descriptors 3 is assigned to /etc/resolv.conf and 4 is assinged to /tmp/output.txt.
- Fd # 0, 1, and 2 are all assinged to /dev/pts/2 i.e. my screen in this output.
- The ls /proc/$mypid/fd command lists all open fds using scripts PID (process identification number) number.
- The proc file system (/proc) is a pseudo-file system which is used as an interface to kernel data structures.
- 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.
- /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