文件名中是否不允许有空格?


31

据说在一般的Unix和Linux上,应该避免文件名(普通文件,dir,链接,设备文件等)中包含空格。

但是我一直都这样做。对于内部带有空格的文件名,

  • 在Nautilus中,空格字符显示为空格。
  • 在Bash终端中,我要么\ 用来表示一个空格,要么将文件名括在一对双引号中。
  • 在某些应用程序的文件中(Nautilus,不确定操作系统是否也会这样做),文件名用空格代替%20

文件名中确实不允许有空格吗?

如何正确使用或处理文件名中的空格?


17
这是允许的,但确实很烦人。没有理由。不要这样
莫妮卡(Monica)与Lightness竞赛

3
您也可以创建一个名为-rf ~(使用touch -- "-rf ~")的文件,但我不建议这样做。
伊恩·斯科特

5
您可以这样做,就像创建一个名为“ cd”的自毁脚本一样,但是您不应该这样做。您的文件在3种不同的工具中看起来已经不一样了,还不够糟糕吗?
Falco 2014年

7
并非所有人都认为这确实非常烦人。而且“没有理由这样做”显然是错误的,以至于不需要反驳。几年前,我屈服并学习了如何正确处理空间,在大多数情况下,这确实没什么大不了的。

2
@snailboat空间是缺乏标准化的实际问题的征兆。Unix文件系统允许文件“名称”几乎为不受限制的二进制Blob。唯一的非法字节是0和47(/分隔符)。使用所有剩余的254个字节为各种难以形容的eldritch“名称”打开了大门。显然这是疯狂的,但是并不是每个人都对“疯狂”表示同意,并且不同的角色会破坏不同的工具。每个人的理智的交集很小
jw013

Answers:


48

/文件名中允许使用空格以及实际上除NUL和NUL 之外的所有字符。建议不要在文件名中使用空格,因为存在这样的危险,即软件支持不佳可能会误解它们。可以说,这种软件是错误的。但是也可以说,诸如shell脚本之类的编程语言使编写带有在其中带有空格的文件名时出现问题的软件写起来太容易了,并且这些bug往往会漏掉,因为开发人员并不经常使用带有空格的文件名来测试shell脚本。他们。

%20在文件名中通常看不到用空格代替。这主要用于(网络)URL。尽管的确,URL的%编码有时会偶然进入文件名。


6
zh_cn.wikipedia.org/wiki/URL_encoding它是“ URL编码”或“百分比编码”。 据称,最合适的名称可能是“ URI编码”,但是人们发现urlURI更容易说,因此这是URI的一种常见形式误称。请注意,URI中的保留字符集大于* nix文件名的保留字符集。
goldilocks

1
@Tim我不知道您可以在中的任何命令行参数中指定NUL字符bash。我尝试了一些操作,例如用Ctrl-V引用它之类的东西,$(echo -e \\0)但是它不起作用。问题是,不能在文件名中使用NUL的原因是它不能在C字符串中使用(因为它是字符串终止符),并且所有底层API以及几乎所有由C程序处理的字符串都使用该格式。由于bash是用C语言编写的,因此对于其中包含NUL的任何字符串,它可能根本不提供任何支持。我可能是错的,可能有一些晦涩的方法……
Celada 2014年

1
排序取决于上下文。字符串函数通常不计算最后一个null(或者,第一个null是字符串的结尾,即使后面还有东西),因此从这种意义上讲,它的长度为零,因此将被视为空。
goldilocks 2014年

3
@Celada当然可以使用NUL并且需要bash $'\0'。例如:find . -print0 | while read -d $'\0' f; do echo "$f"; done
terdon

1
@goldilocks人们实际上将URL发音为“ url”,大致与“ earl”押韵吗?
Miles Rout 2014年

17

如您所见,文件名允许有空格。

如果您在Wikipedia中查看此图表中的“大多数UNIX文件系统”条目,则会注意到:

  • 允许使用任何8位字符集。我们也可以将7位ASCII包含在内,因为它是各种8位集合的子集,并且始终使用8位字节来实现。

  • 唯一禁止使用的字符是/和“ null”。“空”指的是零字节,但是无论如何在文本数据中都不允许这些字节。

但是,如果您使用shell,您可能会意识到有些字符会带来麻烦,最重要的是*,这是POSIX globlob运算符。

根据您要如何定义“麻烦”,您可以在其中包括空格(空格,制表符,换行符等),因为这需要用引起引用""。但这是不可避免的,因为允许有空格,所以...

如何正确使用或处理文件名中的空格?

在外壳程序/命令行上下文中,将文件名用单引号或双引号引起来(但请注意,它们与 WRT其他问题不同),或使用来转义空格\,例如:

> foo my\ file\ with\ spaces\ in\ the\ name

1
如何在bash中指定NUL字符?我想在文件名中对其进行测试。
蒂姆(Tim)

1
你不能 “ execve语义”是指这样的事实:在C语言(以及我所知道的所有其他语言)中,文本字符串以null终止。该外壳程序是用C实现的。我能想到的最偷偷摸摸的是touch $(echo -e "foo\00bar")- -e进程\0N是一个八进制值,但它仍然丢失在某个地方,因为它只是创建了一个名为的文件foobar。当然NULL是不可打印的,但是由于C字符串的限制,我保证它不再存在。
goldilocks 2014年

“文本字符串以null结尾” ->进一步说明:字符串始终以零字节结尾存储,这就是为什么在文本中“不允许”的原因:如果插入一个,则实际上已经终止了字符串在那时候。例如,foo[NULL]bar最终将达到foo大多数意图和目的。事实并非如此,这echo -e表明NULL已被修剪掉。
goldilocks

5
绝大多数编程语言都允许在字符串中使用空字符。碰巧的是,不是主要语言C就是Unix构建的-多数Unix Shell也不允许字符串中的空字符。在任何情况下,@ Tim,所有Unix接口都使用以空字符结尾的字符串,因此,空字节是文件名中永远都不能拥有的一件事(加上/目录分隔符且不能用引号引起来,因此可以在路径名中使用)但不在文件名中)。
吉尔(Gilles)'所以

1
...但是[再也没关系]。无论如何,我不会经常这样做。我认为没有理由将它们包含在文本数据中。我会纠正的,但这是一条评论。
金发姑娘

3

原因很大程度上是历史原因-文件名中不允许使用时空的方式,因此将空格用作关键字/文件名分隔符。未来的Shell解释器必须与旧脚本反向兼容,因此我们陷入了今天的头痛。

不需要太多与人打交道的流程的开发人员可以通过完全减少空间来简化事情。苹果这样做,/ System / Library / CoreServices /的内容只包含很少的空格,带有空格的程序代表用户打开,并且将查找奇怪的如果出现驼峰的情况。类似的unix-only路径也可以避免空格。

(有些相关的轶事:在90年代中期,一架Windows无人机说:“说出您可以在Mac上做的一件事,而在Mac上我不能在Windows上做。”->“在文件名中使用12个字符。”->沉默。空格是也可以用这12个字符表示)


1
我曾经使用V6 Unix(约1978年)。空间,然后允许的。我要做的一个任务是编写一个程序来分析文件系统(使用直接磁盘I / O)并查找名称中包含空格和退格键的文件。
wallyk 2014年

它们会完全删除空格吗?还是文件名包含很少的空格?
mikeserv

2

所以是的,就像在其他地方多次提到的,文件名几乎可以包含任何字符。但需要说是一个文件名不是一个文件。它确实具有文件属性的权重,因为您通常需要一个文件名才能打开文件,但是文件名指向实际文件。它是一个链接,存储在记录该链接的目录中,以及 inode编号 -与实际文件更接近。

因此,您可以随意调用它。内核不在乎-它将处理的所有文件引用无论如何都将处理实际的inode编号。文件名是为了人类 -如果您想使其变得疯狂,那它就是您的文件系统。在这里,我将做一些疯狂的事情:

首先,我将创建20个文件,并将它们命名为空格,每个文件名比最后一个文件名多一个空间:

until [ $((i=$i+1)) -gt 20 ]
do  v=$v' ' && touch ./"$v"
done

这有点好笑。看我的ls

ls -d ./*
./      ./          ./              ./                  ./                 
./      ./          ./              ./                  ./                  
./      ./          ./              ./                  ./                   
./      ./          ./              ./                  ./     

现在,我将镜像该目录:

set -- * ; mkdir ../mirror
ls -i1qdU -- "$@" |
sh -c 'while read inum na
    do  ln -T "$1" ../mirror/$inum
    shift ; done' -- "$@"
ls -d ../mirror/*

这是 ../mirror/的内容:

../mirror/423759  ../mirror/423764  ../mirror/423769  ../mirror/423774
../mirror/423760  ../mirror/423765  ../mirror/423770  ../mirror/423775
../mirror/423761  ../mirror/423766  ../mirror/423771  ../mirror/423776
../mirror/423762  ../mirror/423767  ../mirror/423772  ../mirror/423777
../mirror/423763  ../mirror/423768  ../mirror/423773  ../mirror/423778

好的,但是也许你在问-那有什么好处?你怎么知道哪个是哪个?您甚至如何确保将正确的inode编号链接到正确的文件名?

好...

echo "heyhey" >>./'    ' 
tgt=$(ls -id ./'    ')
cat ../mirror/${tgt%% .*} \
    $(ls -1td ../mirror/* | head -n1) 

输出值

heyhey
heyhey

请参阅,包含在其中的inode编号../mirror/"${tgt%% .*}"和所引用的inode编号均引用./' '同一文件。它们描述相同的文件。他们命名,但仅此而已。实际上,没有什么神秘的地方,您可能会给自己带来一些不便,但最终最终将对unix文件系统的操作几乎没有影响。

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.