cat 和 '>' 之间的区别将文件归零

KM.*_*KM. 24 io-redirection cat

这两个命令在如何将文件清零方面有什么不同吗?后者是做前者的更短的方法吗?幕后发生了什么?

两个都

$ cat /dev/null > file.txt

$ > file.txt 
Run Code Online (Sandbox Code Playgroud)

屈服

-rw-r--r--  1 user  wheel  0 May 18 10:33 file.txt
Run Code Online (Sandbox Code Playgroud)

phe*_*mer 29

cat /dev/null > file.txtcat无用用法

基本上cat /dev/null只是导致cat什么都不输出。是的,它有效,但很多人不赞成它,因为它会导致调用一个不必要的外部过程。
这是那些很常见的事情之一,因为它很常见。

使用 just> file.txt可以在大多数 shell 上工作,但它不是完全可移植的。如果您想要完全便携,以下是不错的选择:

true > file.txt
: > file.txt
Run Code Online (Sandbox Code Playgroud)

两个:true输出没有数据,并且是shell内建(而cat是外部实用程序),因此它们更轻,更“适当的”。

 

更新:

正如 tylerl 在他的评论中提到的,还有>| file.txt语法。

大多数 shell 都有一个设置,可以防止它们通过>. 您必须>|改用。这是为了在您真正想要附加>>. 您可以使用 开启该行为set -C

因此,我认为截断文件的最简单、最合适和可移植的方法是:

:>| file.txt
Run Code Online (Sandbox Code Playgroud)

  • 大声笑,“虐待猫” (4认同)
  • 冒号命令 [在 POSIX 中定义](http://pubs.opengroup.org/onlinepubs/000095399/utilities/colon.html)。它是一个空操作,用于扩展命令行参数。 (3认同)
  • @kojiro `:` 也被 POSIX 强制要求内置,实际上它与 `true` 不同,它被认为是一个 ["special" built-in](http://pubs.opengroup.org/ onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_14)。 (2认同)
  • 不要忘记*noclobber*。`>| file` 是一个更明确的截断。 (2认同)

Sté*_*las 24

在便携性方面:

                      Bourne POSIX  zsh    csh/tcsh  rc/es  fish
> file                Y      Y      N(1)   N(1)      N      N
: > file              N/Y(2) Y(3)   Y      Y(4)      N(5)   N(5)
true > file           Y(5)   Y      Y      Y(5)      Y(5)   Y(5)
cat /dev/null > file  Y(5)   Y      Y(5)   Y(5)      Y(5)   Y(5)
eval > file           Y(3,8) Y(3)   Y      Y(6)      Y      Y
cp /dev/null file (7) Y(5)   Y      Y(5)   Y(5)      Y(5)   Y(5)
printf '' > file      Y(5)   Y      Y      Y(5)      Y(5)   Y
Run Code Online (Sandbox Code Playgroud)

笔记:

  1. 除了 inshkshemulation,对于没有命令的重定向,在 zsh 中,假定默认命令(仅用于 stdin 重定向的寻呼机,cat否则),可以使用 NULLCMD 和 READNULLCMD 变量进行调整。这是受到类似功能的启发(t)csh
  2. 最初:在 UnixV7 中没有执行重定向,因为在:注释前导和空命令之间被解释了一半。后来它们和所有内置函数一样,如果重定向失败,则退出 shell。
  3. :并且eval是特殊的内置bash函数,如果重定向失败,则退出 shell(仅在 POSIX 模式下这样做)。
  4. 有趣的是,在 中(t)csh,它定义了一个空标签(for goto),所以goto ''那里会有分支。如果重定向失败,则退出 shell。
  5. 除非/如果对应的命令是在可用的$PATH:一般不; truecatcpprintf通常是(POSIX要求它们))。
  6. 如果重定向失败,则退出 shell。
  7. file但是,如果是指向不存在文件的符号链接,则某些cp实现(例如 GNU 的实现)将拒绝创建它。
  8. 尽管Bourne shell 的初始版本不支持重定向内置函数

在易读性方面:

(这部分非常主观)

  • > file. 这>看起来太像提示或评论了。另外,我在阅读时会问的问题(大多数 shell 会抱怨相同的问题)是您重定向的输出究竟什么?.
  • : > file. :被称为无操作命令。所以直接读取为生成一个空文件。然而,在这里,:很容易被遗漏和/或被视为提示。
  • true > file与重定向或文件内容有什么关系?这里是什么意思?这是我读到它时想到的第一件事。
  • cat /dev/null > file. 连接/dev/nullfile? cat而往往被视为命令转储文件的内容,仍然是有意义的:转储内容空文件到file,有点像一个令人费解的方式来表达cp /dev/null file,但还是可以理解的。
  • cp /dev/null file. 将空文件的内容复制到file. 是有道理的,虽然有人不知道如何cp意味着默认做可能会认为你在试图让file一个null设备也是如此。
  • eval > fileeval '' > file。不运行任何内容并将其输出重定向到file. 我感觉合理。奇怪的是,这不是一个常见的成语。
  • printf '' > file: 明确地将任何内容打印到文件中。对我来说最有意义的一个。

在性能方面

不同之处在于我们是否使用内置的 shell。如果没有,则必须分叉进程,加载并执行命令。

eval保证在所有 shell 中构建。:内置于任何可用的地方(Bourne/csh 喜欢)。true仅内置在类似 Bourne 的 shell 中。

printf内置了最现代的类似 Bourne 的 shell 和fish.

cp并且cat一般不是内置的。

现在cp /dev/null file不调用 shell 重定向,所以如下:

find . -exec cp /dev/null {} \;
Run Code Online (Sandbox Code Playgroud)

将比:

find . -exec sh -c '> "$1"' sh {} \;
Run Code Online (Sandbox Code Playgroud)

(虽然不一定比:

find . -exec sh -c 'for f do : > "$f"; done' sh {} +
Run Code Online (Sandbox Code Playgroud)

)。

亲身

就个人而言,我: > file在 Bourne-like shell 中使用,并且这些天不使用 Bourne-like shell 以外的任何东西。

  • @kojiro,对于 `dd` 的一些实现(至少像 Solaris 10),忽略 `count=0`。`dd if=/dev/null of=file` 会更便携。无论如何,这与外壳无关。 (2认同)
  • @kojiro,`cp /dev/null file` 是一个常见的习语。我仅限于这些,重点不是列出所有可能的方式。 (2认同)

Fab*_*ian 5

您可能想查看truncate,它的作用正是如此:截断文件。

例如:

truncate --size 0 file.txt
Run Code Online (Sandbox Code Playgroud)

这可能比使用true > file.txt.

然而,我的主要观点是:truncate用于截断文件,而使用 > 具有截断文件的副作用。

  • `truncate` 是一个 FreeBSD 实用程序,最近(2008 年)添加到 GNU coreutils(尽管 `--size` GNU 长选项样式是 GNU 特定的),因此它在非 GNU 或 FreeBSD 系统中不可用,并且它在较旧的 GNU 系统中不可用,我不会说它是可移植的。`cp /dev/null file` 可以在没有 shell 重定向的情况下工作,并且更便携。 (3认同)
  • 当您想将文件截断为 0 以外的内容时,Truncate 非常有用。也就是说,*即使没有 shell* 也是一个奇怪的陈述:您能否描述一个上下文,其中 `truncate` 可用,但 `>` 和 ` unistd` C 库是否可用? (2认同)