将一个文件重定向到另一个文件是否是UUOC(无用的使用cat)?

将一个文件重定向到另一个文件是否是UUOC(无用的使用cat)?

如果我想让 的内容与file2的内容匹配file1,我显然可以运行cp file1 file2

但是,如果我想保留一切关于file2 除了内容——所有者、权限、扩展属性、ACL、硬链接等等,那么我不想运行cp.* 在这种情况下,我只想将 的内容file1放入file2.

似乎以下内容可以做到这一点:

< file1 > file2

但这不起作用。 file2被截断为空并且不被写入。然而,

cat < file1 > file2

工作。

令我惊讶的是第一个版本不起作用。

第二个版本是UUOC吗?有没有一种方法可以在不调用命令的情况下仅通过使用重定向来做到这一点?

注意:我知道 UUOC 更像是一个迂腐的观点,而不是真正的反模式。

*作为tniles09 发现,cp 将要事实上在这种情况下工作。

答案1

cat < file1 > file2不是 UUOC。经典地,<执行>与系统级别的文件描述符重复相对应的重定向。文件描述符重复本身没有任何作用(好吧,>重定向是用 打开的O_TRUNC,所以准确地说,输出重定向会截断输出文件)。不要让这些< >符号让您感到困惑。重定向不会移动数据,而是将文件描述符分配给其他文件描述符。

在这种情况下,您打开file1该文件描述符并将其分配给文件描述符0<file1== 0<file1),file2然后将该文件描述符分配给文件描述符1>file2== 1>file2)。

现在您已经有了两个文件描述符,您需要一个进程来在两个文件描述符之间移动数据——这就是目的cat

答案2

事实并非如此,因为正如其他人指出的那样,所讨论的行为是依赖于 shell 的。正如您(OP)所指出的,这有点迂腐的, 甚至会幽默?,某种主题。

然而,在 GNU 系统上,您的初始前提还有另一个可用的解决方案:cp --no-preserve=all file1 file2。尝试一下,我认为它会满足您所描述的情况(例如修改内容file2而不修改其属性)。

例子:

$ ls -l
    total 8
    -rw-r--r-- 1 tniles sambashare 16 Dec 16 12:21 fezzik
    -rw-r--r-- 1 tniles tniles     14 Dec 16 12:16 fred
$ cat *
    Lookout, world!
    Hello, world!
$ cp --no-preserve=all fred fezzik 
$ ls -l
    total 8
    -rw-r--r-- 1 tniles sambashare 14 Dec 16 12:22 fezzik
    -rw-r--r-- 1 tniles tniles     14 Dec 16 12:16 fred
$ cat *
    Hello, world!
    Hello, world!

更新 实际上,我只是注意到我的系统cp本身似乎保留了属性,除非指定-a或。-p我正在使用 bash shell 和 GNU coreutils。我想你每天都会学到新东西......


测试结果(通过通配符)包括硬链接和不同的权限:

$ ls -li
total 12
913966 -rw-rw-r-- 1 vagrant vagrant 30 Dec 16 20:26 file1
913965 -rwxrw---- 2 pete    vagrant 39 Dec 16 20:35 file2
913965 -rwxrw---- 2 pete    vagrant 39 Dec 16 20:35 hardlinktofile2
$ cat file1
This is the contents of file1
$ cat file2
This is the original contents of file2
$ cp file1 file2
$ ls -li
total 12
913966 -rw-rw-r-- 1 vagrant vagrant 30 Dec 16 20:26 file1
913965 -rwxrw---- 2 pete    vagrant 30 Dec 16 20:37 file2
913965 -rwxrw---- 2 pete    vagrant 30 Dec 16 20:37 hardlinktofile2
$ cat file1
This is the contents of file1
$ cat file2
This is the contents of file1
$ 

答案3

zsh在工作的shell中< file1 > file2,shell 确实调用cat

对于仅包含重定向且没有命令或分配的命令行,zsh将调用$NULLCMDcat默认情况下),除非唯一的重定向是一种重定向,<在这种情况下$READNULLCMDpager默认情况下)将被调用。 (除非zsh是 inshcshemulation,在这种情况下它的行为就像它模拟的 shell)。

所以:

< file1 > file2

实际上是一样的

cat < file1 > file2

< file1

是相同的

pager < file1

答案4

< file1 > file2似乎依赖于 shell,在 zsh 上它可以工作,但在 bash 上则不行。

编辑:删除虚假陈述

相关内容