当目录已存在时,执行mkdir -p命令失败

38

在我们的一个远程系统上,当目录已经存在时,mkdir -p $directory 命令会失败,显示如下信息:

mkdir: cannot create directory '$directory': file exists

这真的很令人困惑,因为我认为-p的合同是,它总是成功,即使目录已经存在。而且,在我尝试过的其他系统上也可以运行。

所有这些系统上都有一个用户test,并且directory=/home/test/tmp

5个回答

51

如果目录中已经存在同名的文件,那么就会导致这种情况发生。

请注意,在Linux机器上,一个目录不能同时包含同名的文件和文件夹。


2
这正是我想要的,我目前正在审查和修复我们的脚本。 - UmNyobe
3
谢谢。在我的情况下,失败是因为有一个同名的符号链接。 - Asu

4

检查是否存在与$directory同名的文件(而非目录)。


4

如果在同一目录下存在同名文件,则mkdir -p不会创建目录。否则,它将按预期工作。


4

你的目录是否是基于FUSE网络挂载?

除了已经存在该名称的文件(其他答案),这种情况可能发生在曾经挂载过某些内容的FUSE进程崩溃(或被杀死,例如使用kill -9或通过Linux OOM killer)的目录上。

mount中检查FUSE挂载是否仍然列在其中。如果是,则应该能够卸载它并使用fusermount -uz修复情况。

要详细了解发生了什么,请运行strace -fy mkdir -p $directory,它会显示所有涉及的系统调用及其返回值。


我认为在这种情况下发出的错误消息是mkdir -p(特别是gnulib库)中的一个错误:

当你在已经挂载了FUSE进程但该进程崩溃的目录上运行它时,它会显示以下信息:

mkdir: cannot create directory ‘/mymount’: File exists

这是相当不准确的,因为底层的stat()调用返回ENOTCONN(传输端点未连接);但mkdir将来自前一个mkdir()系统调用的不太具体的错误向上传播。 这更加令人困惑,因为手册上说:
   -p, --parents
          no error if existing, make parent directories as needed

因此,如果目录存在,它不应该出错,但是ls -l /显示:

d????????? ? ?    ?       ?            ? files

根据此 (d),它是一个目录,但是根据 test -d,它不是。
我相信更好的错误信息(mkdir -p 在这种情况下应该发出)应该是:

mkdir: cannot create directory ‘/mymount’: Transport endpoint is not connected

如果是这种情况,应该怎么修复? - adrian
1
@adrian 修复方法:在 mount 中检查 FUSE 挂载是否仍然存在。如果是,则可以使用 fusermount -uz 卸载它并修复问题。我已经将此添加到答案中了。 - nh2

0
原因:文件名 -p 已经存在。
解释: 你可能会想,当你只创建了一个目录时,为什么会创建一个名为 -p 的文件呢?这是因为在Unix中,所有东西都是文件,即使你创建的目录也是一个文件。
解决方案: 方法1:重命名现有目录(在你的情况下是 '-p')。
sudo mv -p -p/renaming

我们已经将-p移动到一个新目录-p/并重命名为它。 现在,请重新运行该命令。
mkdir -p

这次不应该有任何错误。
你可能会遇到另一个问题:权限被拒绝。 当你没有写入权限时,就会出现这个问题。 你可以通过使用以下方法来检查。
ls -lad -p

你会看到类似这样的内容 'd' 表示这是一个目录,r-x 表示用户只有读/执行的权限,但没有写的权限 所以要给用户授权,使用以下命令:
chmod u+w -p

现在再试一次
ls -lad -p

你会看到 用户现在有写入权限

现在,你可以创建目录

mkdir -p

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接