为什么没有任何Shell命令来创建文件?


27

请注意:

不是在问如何从命令行制作文件!


多年来,我一直touch在制作文件而没有注意它的主要目的是其他东西。如果要从命令行创建文件,则有很多可能性:

touch foo.bar
> foo.bar
cat > foo.bar
echo -n > foo.bar
printf '' > foo.bar

而且我敢肯定还有更多。

但是事实是,以上命令实际上都不是为创建文件而设计的。例如,man touch建议此命令用于更改文件时间戳。为什么没有像Unix(或Linux)那样完整的OS具有专门用于创建文件的命令?


35
您为什么要使系统混乱以添加命令来执行可以使用现有工具进行多种方式进行的操作?
迈克尔·科恩

4
为什么没有命令从流/标准输入/输出中读取文件?每个人都使用cat意味深长的命令!
SF。

2
@MichaelKohne,我很高兴看到你的观点,我对此有疑问。通过这种方法,许多命令只会使系统混乱。为什么用什么more时候less比做更多more!或dirls。虽然,我知道兼容性问题。
2014年

9
more在创建之前lessless专为解决的缺点而创建moremore由于向后兼容的原因,它仍然存在。dir并且ls在大多数情况下都是相同的可执行文件-它们仅在少数字节上有所不同。一个专门用于创建文件的新工具的作用要小于现有工具,因此这将是一种回归,而不是像lessvs 那样的改进more
lanzz 2014年

1
另外,我们需要查看传统,Unix是在计算每个字节时创建的。为什么要为可以使用现有工具执行的任务创建工具?
2014年

Answers:


38

我要说的是,因为几乎不需要创建一个空文件,而不会在命令行或Shell脚本中立即填充内容。

如果首先可以创建文件,然后使用I / O重定向写入文件,则绝对没有任何好处。

在那些您真的想创建一个空文件并将其保留的情况下,我认为这> "${file}"不可能更简短,更优雅。

TL; DR:之所以不存在,是因为创建空文件通常是没有用的,并且在有空文件的情况下,已经有无数的可用选项来实现此目标。

附带说明一下,touch仅当文件不存在时使用才可以使用,而使用重定向的选项将始终截断文件(即使文件存在)(从技术上讲,这些解决方案也不相同)。> foo是首选方法,因为它节省了,fork并且echo -n由于高度不可移植而通常应避免使用。


1
我发现关于创建文件然后使用I / O工具的观点非常可靠。谢谢。
2014年

1
@FaheemMitha是(>>)。我指的是OP使用给出的示例>。如果您要创建的文件是文件,则追加将毫无用处(如果存在,则不进行NOOP操作)。
AdrianFrühwirth2014年

1
不要忘记noclobber不必设置它,这样>将覆盖现有文件。
Ouki 2014年

1
@Ouki AFAIK,该设置不是默认行为,并且可能会忘记它是在一个系统而不是另一个系统上设置的,从而可能以创建alias rm='rm -i'替代的方式产生麻烦,这alias rmi='rm -i'是一个坏主意。
Agi Hammerthief 2014年

1
@mikeserv,> .file仅在命令行上就可以很好地完成,而无需使用:
Charles Duffy 2014年

16

AdrianFrühwirth的答案是正确的。我只是想补充一点,实际上实际上有一个专门用来创建文件的命令:mktemp

NAME
       mktemp - create a temporary file or directory

SYNOPSIS
       mktemp [OPTION]... [TEMPLATE]

DESCRIPTION
       Create a temporary file or directory, safely, and print its name.  TEM
       PLATE must contain at least 3 consecutive 'X's in last  component.   If
       TEMPLATE is not specified, use tmp.XXXXXXXXXX, and --tmpdir is implied.
       Files are created u+rw, and directories  u+rwx,  minus  umask  restric
       tions.

当然,mktemp不是创建具有特定名称的文件,而只是创建文件。但是,正如您已经知道的那样,创建具有给定名称的文件的方法更加高效,优雅,因此提供命令将毫无意义。

这就是说,你还可以truncatefallocate包括其两个主要目的是创建文件。他们只是拥有更复杂的方法。永远不会有一个简单的程序会做什么> file,因为不可能有比它更好的方法> file


11

大多数基本的Shell工具都不为任何特定目的而设计的。大多数基本的Shell工具仅设计用于与其他人交互以实现您的目的。或者也许应该说,大多数工具只做一件非常基本的事情,而不管如何组合才能实现目标。

: >./file

这将创建一个空文件。或截断现有文件。您可以:

set -o noclobber

为了避免后一种情况的任何可能性,除非您:

: >|./file

您可以得到与以下类似的行为touch

: >>./file
: >>|./file

除了:因为它不被修改将不会更新文件的modtime。

演示

mkdir test ; cd $_
touch touch.file 
: >null.file
echo >echo.file
ls -l

输出值

-rw-r--r-- 1 mikeserv mikeserv 1 Apr 10 14:52 echo.file
-rw-r--r-- 1 mikeserv mikeserv 0 Apr 10 14:52 null.file
-rw-r--r-- 1 mikeserv mikeserv 0 Apr 10 14:52 touch.file

不碰

: >>|./echo.file
ls -l 

输出值

-rw-r--r-- 1 mikeserv mikeserv 1 Apr 10 14:52 echo.file
-rw-r--r-- 1 mikeserv mikeserv 0 Apr 10 14:52 null.file
-rw-r--r-- 1 mikeserv mikeserv 0 Apr 10 14:52 touch.file

默认情况下,echo \n在行末添加。尝试echo -n >echo-n.file(size = 0)和echo -e >echo-e.file(size = 1)
Thomas

@Thomas '要写入标准输出的字符串。如果第一个操作数是-n,或者任何一个操作数包含反斜杠('\')字符,则结果是实现定义的。在符合XSI的系统上,如果第一个操作数为-n,则应将其视为字符串,而不是选项。以下字符序列应在符合XSI的系统上的任何自变量中识别...' pubs.opengroup.org/onlinepubs/009604599/utilities/echo.html
mikeserv 2014年

足够公平,感谢您的链接,我的评论仍然不是重点
Thomas

2
是的,确实,很抱歉,我的意思是我的评论无论如何都没有回答您的要点,对此表示抱歉。
2014年

1
Unix泛化趋势的一个例证是,显示文件内容的命令称为cat。当您可以执行一个命令将多个文件连接到标准输出时,为什么要显示一个文件?
200_success 2014年

1

该实用程序install实际上是为创建文件而设计的!您可以通过以下方式传递文件的内容/dev/stdin(但是,在大多数情况下,在大多数Linux上,这要求/proc已挂载)或提供另一个源文件。您可以设置所有权和权限。

echo "New file" | install -o 0644 -m 452452 -g dumbass /dev/stdin /var/www/index.html

作为一个愚蠢的例子。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.