首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Bash读/写文件描述符--查找文件的开头

Bash读/写文件描述符--查找文件的开头
EN

Stack Overflow用户
提问于 2010-10-01 18:23:50
回答 7查看 14.7K关注 0票数 18

我尝试在bash中使用读/写文件描述符,以便可以删除文件描述符随后引用的文件,如下所示:

代码语言:javascript
复制
F=$(mktemp)
exec 3<> "$F"
rm -f "$F"

echo "Hello world" >&3
cat <&3

但是cat命令没有给出任何输出。如果我使用单独的文件描述符来读写,我可以实现我想要的:

代码语言:javascript
复制
F=$(mktemp)
exec 3> "$F"
exec 4< "$F"
rm -f "$F"

echo "Hello world" >&3
cat <&4

它打印Hello world

我怀疑当您从写入切换到读取时,bash不会自动查找文件描述符的开头,以下bash和python代码的组合证实了这一点:

fdrw.sh

代码语言:javascript
复制
exec 3<> tmp
rm tmp

echo "Hello world" >&3
exec python fdrw.py

fdrw.py

代码语言:javascript
复制
import os  

f = os.fdopen(3)
print f.tell()
print f.read()

这就给出了:

代码语言:javascript
复制
$ bash fdrw.sh
12

$ # This is the prompt reappearing

有没有办法只使用bash就能达到我想要的效果?

EN

回答 7

Stack Overflow用户

回答已采纳

发布于 2010-10-01 18:45:31

不是的。bash没有任何“寻找”重定向的概念。它(主要)在一个长流中从头到尾进行读/写。

票数 6
EN

Stack Overflow用户

发布于 2010-10-03 11:08:57

如果需要查找bash文件描述符,可以使用子进程,因为它继承了父进程的文件描述符。下面是一个执行此操作的C程序示例。

seekfd.c

代码语言:javascript
复制
#define _FILE_OFFSET_BITS 64
#include <string.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>

int main(int argc, char* argv[])
{
    /* Arguments: fd [offset [whence]]
     * where
     * fd: file descriptor to seek
     * offset: number of bytes from position specified in whence
     * whence: one of
     *  SEEK_SET (==0): from start of file
     *  SEEK_CUR (==1): from current position
     *  SEEK_END (==2): from end of file
     */
    int fd;
    long long scan_offset = 0;
    off_t offset = 0;
    int whence = SEEK_SET;
    int errsv; int rv;
    if (argc == 1) {
        fprintf(stderr, "usage: seekfd fd [offset [whence]]\n");
        exit(1);
    }
    if (argc >= 2) {
        if (sscanf(argv[1], "%d", &fd) == EOF) {
            errsv = errno;
            fprintf(stderr, "%s: %s\n", argv[0], strerror(errsv));
            exit(1);
        }
    }
    if (argc >= 3) {
        rv = sscanf(argv[2], "%lld", &scan_offset);
        if (rv == EOF) {
            errsv = errno;
            fprintf(stderr, "%s: %s\n", argv[0], strerror(errsv));
            exit(1);
        }
        offset = (off_t) scan_offset;
    }
    if (argc >= 4) {
        if (sscanf(argv[3], "%d", &whence) == EOF) {
            errsv = errno;
            fprintf(stderr, "%s: %s\n", argv[0], strerror(errsv));
            exit(1);
        }
    }

    if (lseek(fd, offset, whence) == (off_t) -1) {
        errsv = errno;
        fprintf(stderr, "%s: %s\n", argv[0], strerror(errsv));
        exit(2);
    }

    return 0;
}
票数 10
EN

Stack Overflow用户

发布于 2014-05-19 05:26:38

我在bash中找到了一种方法,但它依赖于exec < /dev/stdin的一个模糊特性,该特性实际上可以根据http://linux-ip.net/misc/madlug/shell-tips/tip-1.txt倒带标准输入的文件描述符

代码语言:javascript
复制
F=$(mktemp)
exec 3<> "$F"
rm -f "$F"

echo "Hello world" >&3
{ exec < /dev/stdin; cat; } <&3

写描述符不受此影响,因此您仍然可以在cat之前将输出附加到描述符3。

遗憾的是,我只能在Linux下运行,而不能在MacOS (BSD)下运行,即使是最新的bash版本也是如此。所以它看起来并不是很便携。

票数 10
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/3838322

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档