一般的な方法でファイル記述子を明示的に開くことができます。
$ ls -lh /dev/fd/
total 0
lrwx------ 1 tavianator users 64 Jul 10 11:06 0 -> /dev/pts/6
lrwx------ 1 tavianator users 64 Jul 10 11:06 1 -> /dev/pts/6
lrwx------ 1 tavianator users 64 Jul 10 11:06 2 -> /dev/pts/6
lr-x------ 1 tavianator users 64 Jul 10 11:06 3 -> /proc/31288/fd
$ exec 3<foo
$ ls -lh /dev/fd/
total 0
lrwx------ 1 tavianator users 64 Jul 10 11:07 0 -> /dev/pts/6
lrwx------ 1 tavianator users 64 Jul 10 11:07 1 -> /dev/pts/6
lrwx------ 1 tavianator users 64 Jul 10 11:07 2 -> /dev/pts/6
lr-x------ 1 tavianator users 64 Jul 10 11:07 3 -> /home/tavianator/foo
lr-x------ 1 tavianator users 64 Jul 10 11:07 4 -> /proc/31334/fd
今まではそんなに良くなった。 zsh
2桁のファイル記述子構文はサポートされていないようですが、10<foo
変数置換構文はサポートされています{fd}<foo
。
$ fd=10
$ exec {fd}<foo
$ ls -lh /dev/fd/
total 0
lrwx------ 1 tavianator users 64 Jul 10 11:08 0 -> /dev/pts/6
lrwx------ 1 tavianator users 64 Jul 10 11:08 1 -> /dev/pts/6
lr-x------ 1 tavianator users 64 Jul 10 11:08 11 -> /home/tavianator/foo
lrwx------ 1 tavianator users 64 Jul 10 11:08 2 -> /dev/pts/6
lr-x------ 1 tavianator users 64 Jul 10 11:08 3 -> /home/tavianator/foo
lr-x------ 1 tavianator users 64 Jul 10 11:08 4 -> /proc/31413/fd
しかし、待って、なぜfdですか?11代わりに開く10?
答え1
それがZSHが書かれた方法だからです。デフォルトでは、ZSH はファイル記述子を fd 10 にコピーします。
$ PS1='%% ' zsh -f
% lsof -p $$ | grep 10u
zsh 29192 jhqdoe 10u CHR 136,0 0t0 3 /dev/pts/0
%
Src/exec.c
後続の呼び出しのfd関連コードmovefd
/**/
static void
addfd(int forked, int *save, struct multio **mfds, int fd1, int fd2, int rflag,
char *varid)
{
int pipes[2];
if (varid) {
/* fd will be over 10, don't touch mfds */
fd1 = movefd(fd2);
if (fd1 == -1) {
zerr("cannot moved fd %d: %e", fd2, errno);
return;
次に、Src/utils.c
利用可能な10個以上は既に基本的にとられたものなので、最初に見ることができるのは11個の項目を繰り返します。
movefd(int fd)
{
if(fd != -1 && fd < 10) {
#ifdef F_DUPFD
int fe = fcntl(fd, F_DUPFD, 10);
#else
int fe = movefd(dup(fd));
#endif
私のzsh
基準はコードパスをstrace
使用していますが、zshはデフォルトでその番号に重複を格納するため、11で始まる新しいfdを使用できないという意見があります。fcntl
fcntl(...
movefd(dup(...
これ{somelabel}
はすべて10より大きい利用可能な最低ファイル記述子を取得することです。これは、シェルが開いている他の項目に応じて、11またはより高い数字である可能性があります。
% exec {foo}>asdf
% echo $foo
11
% exec {quer}>asdf
% echo $quer
12
...