LinuxQuestions.org
Download your favorite Linux distribution at LQ ISO.
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Forums > Linux Forums > Linux - Newbie
User Name
Password
Linux - Newbie This Linux forum is for members that are new to Linux.
Just starting out and have a question? If it is not in the man pages or the how-to's this is the place!

Notices


Reply
  Search this Thread
Old 12-16-2023, 10:27 AM   #1
jt1122
Member
 
Registered: Apr 2021
Posts: 140

Rep: Reputation: Disabled
file descriptor - exec vs inline


Hi,

What's the difference between using file descriptors (fd) with & without exec?

Example:
This reads a single line on fd 5 from file f:
Code:
read -u5 i 5<f
is the fd "auto" closed after the command finishes?.

With exec (fd opened & closed manually):
Code:
 exec 5<f ; read -u5 i ; exec  5<&-
So the difference is that with exec the fd is permanent until it's manually closed?.

Thanks
 
Old 12-16-2023, 10:33 AM   #2
pan64
LQ Addict
 
Registered: Mar 2012
Location: Hungary
Distribution: debian/ubuntu/suse ...
Posts: 21,864

Rep: Reputation: 7311Reputation: 7311Reputation: 7311Reputation: 7311Reputation: 7311Reputation: 7311Reputation: 7311Reputation: 7311Reputation: 7311Reputation: 7311Reputation: 7311
Code:
read -u5 i 5<f
redirection ( < ) will be valid only during the execution of the command (read).
Code:
exec 5<f
this is a permanent redirection, will be valid until it is closed or the shell exited.
But you know it already.
 
Old 12-16-2023, 10:38 AM   #3
jt1122
Member
 
Registered: Apr 2021
Posts: 140

Original Poster
Rep: Reputation: Disabled
Thanks

So in the example I've given fd 5 will auto-closed after the read command finishes?.

Last edited by jt1122; 12-16-2023 at 10:43 AM.
 
Old 12-16-2023, 02:41 PM   #4
sundialsvcs
LQ Guru
 
Registered: Feb 2004
Location: SE Tennessee, USA
Distribution: Gentoo, LFS
Posts: 10,662
Blog Entries: 4

Rep: Reputation: 3942Reputation: 3942Reputation: 3942Reputation: 3942Reputation: 3942Reputation: 3942Reputation: 3942Reputation: 3942Reputation: 3942Reputation: 3942Reputation: 3942
Quote:
Originally Posted by pan64 View Post
this is a permanent redirection, will be valid until it is closed or the shell exited.
But you know it already.
Worth pointing out, however, that this sort of thing is a bad idea because most programmers will not know to expect it when they are looking for a bug ... this qualifies as "a surprise."
 
Old 12-16-2023, 06:45 PM   #5
MadeInGermany
Senior Member
 
Registered: Dec 2011
Location: Simplicity
Posts: 2,798

Rep: Reputation: 1201Reputation: 1201Reputation: 1201Reputation: 1201Reputation: 1201Reputation: 1201Reputation: 1201Reputation: 1201Reputation: 1201
Code:
read -u5 i 5<f
The shell opens and closes the file just for this one command.
No need for the extra descriptor here.
Code:
read i <f
The shell opens and closes the file via stdin, then the original stdin continues.

The exec lets the shell permanently open the file. Until it's closed with another exec.
Code:
exec 5<f
read -u5 line1
read -u5 line2
exec 5<&-
The extra descriptor makes sense, because I could access the stdin in addition.
But I prefer a code block in favor of an exec/exec.
Code:
{
read -u5 line1
read -u5 line2
} 5<f
The shell opens/closes the file at the beginning/end of the block.
If the block is very long, I usually put a comment at the beginning:
Code:
# &5 is from file f
BTW the -u is never really needed; the standard shell has
Code:
{
read line1 <&5
read line2 <&5
} 5<f

Last edited by MadeInGermany; 12-16-2023 at 07:11 PM.
 
1 members found this post helpful.
Old 12-17-2023, 02:48 AM   #6
pan64
LQ Addict
 
Registered: Mar 2012
Location: Hungary
Distribution: debian/ubuntu/suse ...
Posts: 21,864

Rep: Reputation: 7311Reputation: 7311Reputation: 7311Reputation: 7311Reputation: 7311Reputation: 7311Reputation: 7311Reputation: 7311Reputation: 7311Reputation: 7311Reputation: 7311
Quote:
Originally Posted by MadeInGermany View Post
Code:
read -u5 i 5<f
The shell opens and closes the file just for this one command.
No need for the extra descriptor here.
Code:
read i <f
The shell opens and closes the file via stdin, then the original stdin continues.
Yes, the latter is better, the original way may fail if fd=5 is already in use.

Quote:
Originally Posted by MadeInGermany View Post
The exec lets the shell permanently open the file. Until it's closed with another exec.
Code:
exec 5<f
read -u5 line1
read -u5 line2
exec 5<&-
The extra descriptor makes sense, because I could access the stdin in addition.
To avoid conflict with existing (already used file descriptors) you can try to use 99 instead of 5, but there is a way to dynamically and automatically find the next free one:

Code:
exec {FD}<f
read -u$FD line1
read -u$FD line2
exec $FD<&-

https://tldp.org/LDP/abs/html/io-redirection.html
 
1 members found this post helpful.
Old 12-17-2023, 03:28 AM   #7
syg00
LQ Veteran
 
Registered: Aug 2003
Location: Australia
Distribution: Lots ...
Posts: 21,129

Rep: Reputation: 4121Reputation: 4121Reputation: 4121Reputation: 4121Reputation: 4121Reputation: 4121Reputation: 4121Reputation: 4121Reputation: 4121Reputation: 4121Reputation: 4121
My needs in these things are always modest, but I do enjoy the discussions. Thanks to all.
 
Old 12-17-2023, 04:35 AM   #8
MadeInGermany
Senior Member
 
Registered: Dec 2011
Location: Simplicity
Posts: 2,798

Rep: Reputation: 1201Reputation: 1201Reputation: 1201Reputation: 1201Reputation: 1201Reputation: 1201Reputation: 1201Reputation: 1201Reputation: 1201
Only the exec overwrites a previous file descriptor!
A redirected command sets a file descriptor in a new context:
Code:
exec 5< /etc/nsswitch.conf
read -u 5 passwd1 5< /etc/passwd
read -u 5 nsswitch1
exec 5<&-

echo "$nsswitch1"
echo "$passwd1"
Behind the scene the shell forks; in the forked shell it sets the descriptor then execs the command.

Regarding the redirected code block, it opens a new descriptor context but not a new shell scope (no fork).
Example with nested code blocks:
Code:
exec 5< /etc/nsswitch.conf
{
  {
    read -u 5 passwd1
  } 5< /etc/passwd
  read -u 5 group1
} 5< /etc/group
read -u 5 nsswitch1
exec 5<&-
 
echo "$nsswitch1"
echo "$passwd1"
echo "$group1"
The old Bourne shell forked a sub shell for a redirected code block; shell variables and settings in the sub shell were lost when back in the main shell.
A modern shell avoids a sub shell, unless you enforce it by using ( ) instead of { }
But a pipe from/to a code block still enforces a sub shell.
Code:
echo hello | while read i; do echo "Sub shell: i=$i"; done
echo "Back in the main shell: i=$i"
The while-do-done block is a code block.

BTW even for-do-done if-then-fi case-esac are code blocks. For ex you can do
Code:
if [ "$1" = "head" ]
then
  head
else
  tail
fi < /etc/group
 
  


Reply



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
What is the difference between "exec 5 > myfile" and "exec 2 > myfile"? thomas2004ch Programming 2 02-13-2012 08:19 PM
Get the absolute path of file using file descriptor. appas Programming 7 01-19-2012 11:47 AM
difference between socket returned descriptor and accept returned descriptor naveenisback Programming 1 08-29-2009 04:55 AM
exec cmd=perl... work but exec cgi doenst crions Slackware 5 12-09-2005 12:17 PM

LinuxQuestions.org > Forums > Linux Forums > Linux - Newbie

All times are GMT -5. The time now is 01:15 AM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration