Linux 为什么复制的文件一直增加dup后缀?
dup函数只有一个参数,也就是输入一个fd,可是没有另外一个参数说,要把这个fd复制给谁?
企业建站必须是能够以充分展现企业形象为主要目的,是企业文化与产品对外扩展宣传的重要窗口,一个合格的网站不仅仅能为公司带来巨大的互联网上的收集和信息发布平台,创新互联面向各种领域:成都公路钻孔机等成都网站设计公司、营销型网站建设解决方案、网站设计等建站排名服务。
下面这个小程序,调用fd的结果是,打开的一个文件fd被复制到了标准输出,以至于execl调用的打印内容,被重定向到了文件当中。
#include stdio.h
#include stdlib.h
#include sys/types.h
#include unistd.h
#include fcntl.h
#include sys/stat.h
int main(void){
int filedes;
if((filedes=open("dd.txt",O_WRONLY|O_CREAT,S_IRUSR|S_IWUSR))0)
fprintf(stderr,"%s ","open file error");
close(1);
dup(filedes);
close(filedes);
execlp("ls","-l",(char * )0);
return 0;
}
所以看起来dup程序就是要复制一个fd到stdout。是这样的吗,如果我要dup到stdout以外的fd怎么办呢?
------解决思路----------------------
dup返回的是当前最小可用描述符,你这里会重定向到标准输出是因为你close(1),使标准输出描述符可以被用,所以dup返回了1.
如果我要dup到stdout以外的fd,使用dup2
Linux dup dup2函数理解
在linux中,我们需要复制文件描述符,下面是我对文件描述符的理解
int dup(int fd); // 复制一个已经存在的文件描述符,如果成功,返回复制成功后的文件描述符,失败返回-1
int dup(int fd, int fd2); // 复制一个文件描述符,fd表示已经存在的打开的文件描述符,fd2是指定新的文件描述符,如果fd2等于fd,则直接返回,如果fd2存在并且打开,则先close(fd2)后,重新打开,这样fd2和fd就指向了同一个文件(共享打开的文件),如果fd2不存在或者没有打开,则打开fd2,并且指向fd所指向的文件。函数的返回值和fd2一致。该函数可以实现文件的重定位。
每个进程都有一个文件描述符表,每个描述符占用一个描述符项,每个文件描述符可以描述成这样
struct fileDescription {
int index;
void *pointer;
};
除了整形,还有一个指针,指向文件表,内核为所有打开文件维持一张文件表,每个文件表项包含:
1)文件状态标志(读、写、添写、同步和非阻塞等)
2)当前文件的偏移量
3)指向该文件v节点表项的指针
v节点表中包含了文件所有者、文件长度、文件所在的设备、指向文件实际数据块在磁盘上所在位置的指针等等
下面给出一个例子:
#include iostream
#include stdio.h
#include fcntl.h
#include sys/stat.h
#include unistd.h
#include string.h
using namespace std;
int main()
{
cout "Hello world!" endl;
int fd = open("a.txt", O_RDWR | O_CREAT | O_APPEND, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
if (fd 0)
{
printf("open a.txt failed, fd = %d\n", fd);
return -1;
}
printf("open a.txt success, fd = %d\n", fd);
fflush(stdout);
// 复制标准输出的文件描述符
int nfd = dup(STDOUT_FILENO);
int fileFd = dup2(fd, STDOUT_FILENO);
if (fileFd 0)
{
printf("dup2 stdout_fileno failed, fileFd = %d\n", fileFd);
return -1;
}
printf("重定向标准输出到a.txt, fileFd = %d\n", fileFd);
// 将STDOUT_FILENO复制到fd后,fd并没有发生变化,依然可以通过它写入到a.txt中
const char *pStr = "write string through fd\n";
write(fd, pStr, strlen(pStr));
fileFd = dup2(nfd, fileFd);
if (fileFd 0)
{
printf("dup2 reback stdout_fileno failed\n");
return -1;
}
printf("print back to stdout standard, fileFd = %d\n", fileFd);
// 上面使用dup2的时候,STDOUT_FILENO是存在并打开的,我们来测试下不存在的文件描述符的情况
fileFd = dup2(fd, 20);
if (fileFd 0)
{
printf("dup2不存在的文件描述符失败, fileFd = %d\n", fileFd);
}
else
{
printf("dup2不存在的文件描述符成功, fileFd = %d\n", fileFd);
const char *pStr = "write string through fileFd\n";
write(fileFd, pStr, strlen(pStr));
}
close(nfd);
close(fileFd);
return 0;
}
文件指针是关键,标志两个文件描述符是否一致,看文件指针是否一致即可 ,如果两个或者多个文件描述符指向同一个文件表,那么对他们的操作是对同一个文件进行操作
linux下C语言编程,管道,dup,fork,疑问的是,为什么连用那么多close?必须要close? 代码如下
文件描述符0,1,2分别表示标准输入标准输出,标准错误输出, 所以在子进程里close(1)是关闭了标准输出, 然后用dup(fda[1]);此时未用的最小文件描述符就是1(被关闭);这里关闭fda[0]就是为了说明在子进程是管道的写端(fda[0],不关闭是可以的为了保险起见关闭).然后子进程退出会调用系统程序ls,于是当前的文件目录就被发送到管道中.父进程同理, 就是将标准输出作为管道的读端,它读到的是子进程ls后的内容,对文件计数,
求linux命令 打印文本文件内容到控制台 多个文件可以左右分栏打印, 我记得有这么一个命令,想不起来了
最简单的你 a.out 1.txt
或者用dup2,重定向。
你首先要搞清楚控制台上的输出是怎么输出的,比如说是程序里面printf出来的, 脚本里面echo出来的等等。
然后做一个写日志的函数代码那个输出。也可以把标准输出的文件描述符dup到你要写的文件上面。
最简单的你 a.out 1.txt
或者用dup2,重定向。
函数执行,产生的标准输出,已经再控制台了,我再把它重定向。
你首先要搞清楚控制台上的输出是怎么输出的,比如说是程序里面printf出来的, 脚本里面echo出来的等等。
然后做一个写日志的函数代码那个输出。也可以把标准输出的文件描述符dup到你要写的文件上面。
execvp(args[0], args) 这个函数运行产生的结果。
使用命令重定向操作符可以使用重定向操作符将命令输入和输出数据流从默认位置重定
向到不同的位置。输入或输出数据流的位置即为句柄。
下表将列出可用的句柄。
句柄 句柄的数字代号 描述
STDIN 0 键盘输入
STDOUT 1 输出到命令提示符窗口
STDERR 2 错误输出到命令提示符窗口
UNDEFINED 3-9 这些句柄由应用程序单独定义,并且是各个工具特定的。
数字 0 到 9 代表前 10 个句柄。可以使用命令 Cmd.exe 运行程序并将该程序前 10 个
句柄中的任何一个重定向。要指定想使用的句柄,可在重定向操作符前面键入该句柄的
数字。如果未定义句柄,则默认的 重定向输入操作符是 0,而默认的 重定向输出
操作符是 1。键入 或 操作符之后,必须指定要读取或写入数据的位置。可以指定
文件名或另一个现有的句柄。
要指定重定向到现有句柄,请使用与 () 字符,后面接要重定向的句柄号
(例如 句柄#)。例如,下面的命令可以将句柄 2(即 STDERR)重定向到
句柄 1(即 STDOUT):
21
下表列出了可用于将输入和输出数据流进行重定向的操作符。
重定向操作符 描述
将命令输出写入到文件或设备(例如打印机)中,而不是写在命令提示符窗口或句柄中。
从文件中而不是从键盘或句柄中读入命令输入。
将命令输出添加到文件末尾而不删除文件中的信息。
将一个句柄的输出写入到另一个句柄的输入中。
从一个句柄读取输入并将其写入到另一个句柄输出中。
| 从一个命令中读取输出并将其写入另一个命令的输入中。也称作管道。
默认情况下,可以从键盘将命令输入(即 STDIN 句柄)发送到 Cmd.exe,然后由
Cmd.exe 将命令输出(即 STDOUT 句柄)发送到命令提示符窗口。
重定向输入 ()
要将键盘输入重定向到文件或设备,请使用 操作符。例如,要从 File.txt 获取
sort 命令的输入,请键入:
sortfile.txt
File.txt 的内容将以字母顺序列表的方式显示在命令提示符窗口中。
操作符可以打开具有只读访问的指定文件名。所以,不能使用该操作符向文件中写入
信息。例如,如果以 2 启动程序,则所有试图读取句柄 0 的操作都将失败,因为句
柄 2 最初是以只写访问打开的。
注意
0 是 重定向输入操作符的默认句柄。
重定向输出 ()
几乎所有的命令都将输出发送到命令提示符窗口。即使将输出发送到驱动器或打印机的
命令也会在命令提示符窗口显示消息和提示。
要将输出从命令提示符窗口重定向到文件或设备,请使用 操作符。可以在许多命令中
使用该操作符。例如,要将 dir 输出重定向到 Dirlist.txt,请键入:
dirdirlist.txt
如果 Dirlist.txt 不存在,Cmd.exe 将创建该文件。如果 Dirlist.txt 存在,Cmd.exe
将使用 dir 命令的输出替换文件中的信息。
要运行 netsh routing dump 命令,然后将输出发送到 Route.cfg,请键入:
netsh routing dumpc:\route.cfg
操作符可以打开具有只写访问属性的指定文件。所以,不能使用该操作符读取文件。
例如,如果使用重定向 0 启动程序,则所有试图写入句柄 1 的操作都将失败,因为
句柄 0 最初是以只读访问打开的。
注意
1 是 重定向输出操作符的默认句柄。
复制句柄
重定向操作符 可以将输出或输入从一个指定句柄复制到另一个指定的句柄。例如,
要将 dir 输出发送到 File.txt 并将错误输出发送到 File.txt,请键入:
dirc:\file.txt 21
复制句柄时,可以复制该句柄原状态的所有特性。例如,如果一个句柄具有只写访问的
属性,则该句柄的所有副本都具有只写访问属性。不能将一个具有只读访问属性的句柄
复制到另一个具有只写访问属性的句柄。
使用 操作符重定向输入和副本
要将重定向输入操作符 () 与复制操作符 () 一起使用,指定的文件必须已经存在。
如果输入文件存在,Cmd.exe 将以只读方式打开该文件,然后将文件中包含的字符作为
输入发送到此命令(如同从键盘输入一样)。如果指定了句柄,Cmd.exe 将指定的句柄
复制到系统现有的句柄中。
例如,要以句柄 0 输入读取(即 STDIN)的方式打开 File.txt,请键入:
file.txt
要打开 File.txt,并在内容排序后将输出发送到命令提示符窗口(即 STDOUT),请键入:
sortfile.txt
要查找 File.txt,然后将句柄 1(即 STDOUT)和句柄 2(即 STDERR)重定向到
Search.txt,请键入:
findfile file.txtsearch.txt 21
要以句柄 0 输入读取(即 STDIN)的方式复制用户定义句柄 3,请键入:
3
使用 操作符重定向输出和复制
如果将输出重定向到文件且指定了现有的文件名,Cmd.exe 将以只写方式打开文件并覆
盖该文件内容。如果指定了句柄,Cmd.exe 将文件复制到现有句柄中。
要将用户定义句柄 3 复制到句柄 1,请键入:
3
要将包括句柄 2(即 STDERR)的所有输出从 ipconfig 命令重定向到
句柄 1(即 STDOUT),然后将输出重定向到 Output.log,请键入:
ipconfig.exeoutput.log 21
使用 重定向操作符追加输出
要从命令中将输出添加到文件末尾而不丢失文件中已存在的任何信息,请使用两个连续
的大于号(即 )。例如,下面的命令可以将由 dir 命令生成的目录列表追加到
Dirlist.txt 文件:
dirdirlist.txt
要将 netstat 命令的输出追加到 Tcpinfo.txt 的末尾,请键入:
netstattcpinfo.txt
使用管道操作符 (|)
管道操作符 (|) 可以提取一个命令的输出(默认情况下是 STDOUT),然后将其导入另
一个命令的输入中(默认情况下是 STDIN)。例如,下面的命令将对目录分类:
dir | sort
在本例中,将同时启动两个命令,但随后 sort 命令会暂停,直到它接收到 dir 命令
的输出为止。sort 命令使用 dir 命令的输出作为输入,然后将输出发送到
句柄 1(即 STDOUT)。
合并带重定向操作符的命令
可以通过合并带有其他命令和文件名的筛选器命令创建自定义命令。例如,可以使用以
下命令存储包含“LOG”字符串的文件名:
dir /b | find "LOG" loglist.txt
dir 命令的输出通过 find 筛选器命令发送。包含字符串 "LOG" 的文件名作为文件名
列表(例如,NetshConfig.log、Logdat.svd 和 Mylog.bat)存储在文件
Loglist.txt 中。
要在相同命令中使用多个筛选器,请使用管道 (|) 分隔筛选器。例如,下面的命令将
搜索 C 盘上的每个目录以查找包含 "LOG" 字符串的文件名,并且在命令提示符窗口中
每次显示一屏:
dir c:\ /s /b | find "LOG" | more
利用管道 (|) 可以将 Cmd.exe 导向为通过 find 筛选器命令发送 dir 命令输出。
find 命令只选择包含字符串 "LOG" 的文件名。more 命令可以显示由 find 命令选择
的文件名(在命令提示符窗口中每次显示一屏)。有关筛选器命令的详细信息,请参阅
使用筛选器。
新闻标题:duplinux命令 linux du命令详解
链接地址:http://scgulin.cn/article/dociesg.html