$exec 3<input.txt
$sleep 60 >&3 &
[1] 32524
$ cd/proc/32534/fd
$ ls -l
lrwx------. 1 zhangchen zhangchen 64 Sep 24 18:29 0 -> /dev/pts/0
lr-x------. 1 zhangchen zhangchen 64 Sep 24 18:29 1 -> /home/zhangchen/input.txt
lrwx------. 1 zhangchen zhangchen 64 Sep 24 18:29 2 -> /dev/pts/0
lr-x------. 1 zhangchen zhangchen 64 Sep 24 18:29 3 -> /home/zhangchen/input.txt
$grep test_word <&3
test_word
$grep test_word <&3
[nothing output]
Isn't grep search the file using describer 1, why did grep change the file describer 3?
It's not changing which file is open on FD 3, or what the contents of that file are. What changes is where in the file you're at.
You're opening input.txt
once.
Before you run grep, the file pointer is at the front of the file.
After you run grep, the file pointer is at the end of the file.
It still points to the same file, but you're not at the front of it anymore, so there's no content left to read if the program you're running doesn't use seek()
to rewind to the front.
You can rewind to the front, if you run a program that does so:
# Define a "rewind" function that uses Python
rewind() {
python -c 'import os, sys; os.lseek(int(sys.argv[1]), 0, os.SEEK_SET)' "$@"
}
# Create our input file
echo 'test_word' >input.txt
# Redirect from the input file
exec 3<input.txt
# Read from the input file once
grep test_word <&3
# Rewind the input file back to the beginning
rewind 3
# _Now_ we can read from the input file a second time
grep test_word <&3