mkdir 命令详解与参数实测(Ubuntu 22.04)

mkdir 命令逐参数实测详解:默认权限与 umask、-p 递归创建与幂等语义、-m 创建时设权、-v 冗余输出、父目录缺失与目录已存在的报错回显与退出码,全部命令与回显在 Ubuntu 22.04(GNU coreutils 8.32)实测通过。

Linux命令Linux系统UbuntuUbuntu 22.04命令行文件管理2026/10/15

mkdir 命令详解与参数实测(Ubuntu 22.04)

目标:全面掌握 GNU mkdir 的每一个参数——默认用法与 umask 决定的默认权限、-p 递归创建与幂等语义、-m 创建时设权、-v 冗余输出,以及父目录缺失、目录已存在等错误场景的回显与退出码,全部命令与回显已在 Ubuntu 22.04(GNU coreutils 8.32)实测通过。

一、环境信息

本节记录实测环境与演示数据。mkdir 职责单一(创建目录),但默认权限从哪来、-p 为什么能让脚本幂等,是日常最容易含糊的两点,实测数据围绕它们设计。

  • 操作系统:Ubuntu 22.04.5 LTS(x86_64)
  • mkdir 版本:GNU coreutils 8.32(mkdir --version 实测)
  • mkdir 属于 coreutils 基础工具集,Ubuntu 22.04 默认预装,无需额外安装
  • 演示目录:/root/demo/mkdir/
  • 测试数据:以 root 身份(umask 0022)创建多组目录,覆盖默认权限、指定权限、多级路径、重名/缺父目录等场景

二、命令概览

2.1 语法与测试数据准备

mkdir 的语法是 mkdir [OPTION]... DIRECTORY...:可以一次传入多个目录名(空格分隔),逐个创建;默认行为是"只建最末一级目录,且父目录必须已存在"。

💡 技术拓展:"得到一个目录"有几种不同途径,横向对比——

方式原理/职责适用场景
mkdir从零创建目录,-p 一次建多级且幂等最直接的建目录方式
install -d建目录同时指定属主/属组/权限部署脚本里一步到位建好权限
cp -r复制现有目录树生成新目录需要连内容一起复用模板时
ln -s建指向已有目录的软链(不新建实体)同一目录需要多个访问入口

本文主角是 mkdir:纯创建、不碰内容,-p(多级 + 幂等)与 -m(创建时设权限)是最常用的两个参数。

先准备演示根目录(-p 保证重复执行不报错)并验证就绪:

$ mkdir -p /root/demo/mkdir
$ ls -ld /root/demo/mkdir
drwxr-xr-x 15 root root 4096 Oct 15 06:32 /root/demo/mkdir

再看默认权限的计算依据 umask:

$ umask
0022

umask 0022 表示新建目录时从满权限 777 里扣除 022(组与其他人的写权限),得到默认 drwxr-xr-x(755)——这将在 3.1 与 3.4 的实测里反复得到印证。

2.2 --help 全量回显

mkdir --help 的完整输出如下(实测原样保留,可作参数速查):

Usage: mkdir [OPTION]... DIRECTORY...
Create the DIRECTORY(ies), if they do not already exist.

Mandatory arguments to long options are mandatory for short options too.
  -m, --mode=MODE   set file mode (as in chmod), not a=rwx - umask
  -p, --parents     no error if existing, make parent directories as needed
  -v, --verbose     print a message for each created directory
  -Z                   set SELinux security context of each created directory
                         to the default type
      --context[=CTX]  like -Z, or if CTX is specified then set the SELinux
                         or SMACK security context to CTX
      --help     display this help and exit
      --version  output version information and exit

GNU coreutils online help: <https://www.gnu.org/software/coreutils/>
Report any translation bugs to <https://translationproject.org/team/>
Full documentation <https://www.gnu.org/software/coreutils/mkdir>
or available locally via: info '(coreutils) mkdir invocation'

💡 说明:功能参数就三个——-m(创建时设权限,注意帮助原文强调 "not a=rwx - umask",即不受 umask 影响)、-p(父目录按需创建且已存在不报错)、-v(每个创建动作打印一条消息);-Z/--context 只在 SELinux/SMACK 环境下有意义,Ubuntu 22.04 桌面/服务器默认未启用 SELinux,本文不做展开。

2.3 版本确认

$ mkdir --version | head -1
mkdir (GNU coreutils) 8.32

三、参数逐项实测

3.1 默认用法:父目录存在时创建

父目录就绪时,mkdir 直接创建末级目录,权限为 777 减 umask:

$ mkdir /root/demo/mkdir/default
$ ls -ld /root/demo/mkdir/default
drwxr-xr-x 2 root root 4096 Oct 15 06:10 /root/demo/mkdir/default

drwxr-xr-x 正是 777 扣除 umask 0022 的结果(2.1 的 umask 实测在此闭环);链接数 2 是每个新建目录的起点(自身 . 加父目录中的一项)。

💡 提示:想让"默认权限"整体变化,改 umask;只想改变某一个目录的权限,用 -m(见 3.4)或事后 chmod。

3.2 错误场景:父目录缺失与目录已存在

默认用法有两个高频报错。第一,中间父目录不存在——一次只建末级,路径中任何一层缺失都整体失败:

$ mkdir /root/demo/mkdir/x/y/z
mkdir: cannot create directory '/root/demo/mkdir/x/y/z': No such file or directory
$ mkdir /root/demo/mkdir/x/y/z; echo exit=$?
mkdir: cannot create directory '/root/demo/mkdir/x/y/z': No such file or directory
exit=1

报错点出的是第一个缺失层所在的整体路径(x 还不存在),退出码 1。第二,目录已存在:

$ mkdir /root/demo/mkdir/single
mkdir: cannot create directory '/root/demo/mkdir/single': File exists

失败退出码同为 1:

$ mkdir /root/demo/mkdir/a; echo exit=$?
mkdir: cannot create directory '/root/demo/mkdir/a': File exists
exit=1

多参数时逐个处理、报错不中断后续参数(三个都失败就报三条):

$ mkdir /root/demo/mkdir/a /root/demo/mkdir/b /root/demo/mkdir/c
mkdir: cannot create directory '/root/demo/mkdir/a': File exists
mkdir: cannot create directory '/root/demo/mkdir/b': File exists
mkdir: cannot create directory '/root/demo/mkdir/c': File exists

两类错误的解法都是 -p:前者补齐父目录,后者把"已存在"降级为成功(见 3.3)。

💡 提示:报错信息格式固定为 mkdir: cannot create directory '路径': 原因,脚本里可按原因字段区分 "No such file or directory"(缺父目录)与 "File exists"(重名)。

3.3 -p:递归创建 + 已存在不报错(幂等)

-p(--parents)做两件事:按需创建全部缺失的父目录;目标已存在时静默成功。先看递归——上一节失败的路径一次建到 z,ls -lR 确认 x、x/y、x/y/z 三层全部建出且权限都是默认的 drwxr-xr-x:

$ mkdir -p /root/demo/mkdir/x/y/z
$ ls -lR /root/demo/mkdir/x
/root/demo/mkdir/x:
total 4
drwxr-xr-x 3 root root 4096 Oct 15 06:10 y

/root/demo/mkdir/x/y:
total 4
drwxr-xr-x 2 root root 4096 Oct 15 06:10 z

/root/demo/mkdir/x/y/z:
total 0

再看重名场景:上一节报 File exists 的目录 a,加 -p 后退出码直接归零且无任何输出:

$ mkdir -p /root/demo/mkdir/a; echo exit=$?
exit=0

-v 与 -p 组合能把每一层的创建动作都打印出来,排查多级路径时一目了然:

$ mkdir -v -p /root/demo/mkdir/p1/p2/p3
mkdir: created directory '/root/demo/mkdir/p1'
mkdir: created directory '/root/demo/mkdir/p1/p2'
mkdir: created directory '/root/demo/mkdir/p1/p2/p3'

💡 提示:-p 的"已存在不报错"只针对目录;同名普通文件/软链占位时仍会报错(File exists),这是脚本能依赖的语义边界。

3.4 -m:创建时设置权限

-m MODE 在创建的同一瞬间设定权限(按 chmod 的模式语法),不经过 umask 扣减。与默认权限对照实测:

$ mkdir -m 700 /root/demo/mkdir/private
$ mkdir -m 755 /root/demo/mkdir/shared
$ ls -ld /root/demo/mkdir/private /root/demo/mkdir/shared
drwx------ 2 root root 4096 Oct 15 06:10 /root/demo/mkdir/private
drwxr-xr-x 2 root root 4096 Oct 15 06:10 /root/demo/mkdir/shared
$ mkdir /root/demo/mkdir/default
$ ls -ld /root/demo/mkdir/default
drwxr-xr-x 2 root root 4096 Oct 15 06:10 /root/demo/mkdir/default

-m 700 得到 drwx------(仅属主可进),-m 755 与不加 -m 的默认结果相同(因为默认恰好就是 755)。帮助原文 "not a=rwx - umask" 强调了它与 umask 的无关性——即使 umask 是 0077,-m 755 也能建出 755。

💡 提示:-m 只作用于最末级目录;-p 递归补出来的中间层仍按 umask 创建。要整条链都收紧,需要补一句对中间层的 chmod。

3.5 -v:冗余输出

-v(--verbose)为每个实际创建动作打印一条 mkdir: created directory '路径':

$ mkdir -v /root/demo/mkdir/verbose1
mkdir: created directory '/root/demo/mkdir/verbose1'

多参数 + 重名组合下,报错与创建逐条交替输出,互不影响:

$ mkdir -v /root/demo/mkdir/verbose1 /root/demo/mkdir/verbose2
mkdir: cannot create directory '/root/demo/mkdir/verbose1': File exists
mkdir: created directory '/root/demo/mkdir/verbose2'

第一个参数重名报错,第二个照常创建——印证 3.2 的"逐参数处理、不中断"。

💡 提示:-v 单独用只能看见"建了什么";配合 -p 才能看到"中间补了哪几层"(3.3 实测的三行 created)。审计类脚本建议常开。

四、实战示例

4.1 一条命令搭好项目目录骨架

-p + 多参数,一行建出三层结构的三个分支:

$ mkdir -p /root/demo/mkdir/proj/conf /root/demo/mkdir/proj/logs /root/demo/mkdir/proj/data
$ ls /root/demo/mkdir/proj
conf
data
logs

proj 及其三个子目录全部由这一条命令创建,ls 确认骨架就位。

4.2 创建仅限属主进入的发布目录

-m 与 -v 组合,创建即设定严格权限并留痕:

$ mkdir -m 750 -v /root/demo/mkdir/deploy
mkdir: created directory '/root/demo/mkdir/deploy'
$ ls -ld /root/demo/mkdir/deploy
drwxr-x--- 2 root root 4096 Oct 15 06:32 /root/demo/mkdir/deploy

drwxr-x---(750):属主读写执行、组只读执行、其他人无任何权限——部署目录的常见基线。

4.3 幂等脚本写法:先判断再创建

-p 天然幂等,配合 test -d 可显式表达"不存在才建"的意图:

$ test -d /root/demo/mkdir/proj/logs || mkdir -p /root/demo/mkdir/proj/logs
$ echo guard_exit=$?
guard_exit=0

目录已存在时 test 短路,|| 右侧不再执行,退出码 0;不存在时才触发 mkdir -p。两种情况脚本都能安全重跑。

五、注意事项与常见问题

Q1:mkdir 报 "No such file or directory",路径明明只差最后一级? 默认用法只建末级目录,中间任何一层缺失都会整体失败(3.2 实测 x/y/z)。加 -p 按需补齐全部父目录(3.3 实测)。

Q2:重复运行脚本时报 "File exists" 怎么消除? 给 mkdir 加 -p:目标目录已存在时静默成功、退出码 0(3.3 用重名的 a 目录实测对比:不加 -p 退出码 1,加 -p 退出码 0)。

Q3:新目录的默认权限是怎么算出来的? 777 减去 umask:umask 0022 时得 755(drwxr-xr-x,3.1 实测)。同理 umask 0077 时默认是 700。查当前 umask 直接敲 umask(2.1 实测 0022)。

Q4:-m 700 之后又想放宽,用 mkdir 再改不了怎么办? -m 只在创建瞬间生效,事后调整用 chmod 750 目录。-m 的价值是消除"先建后改"之间被其他进程窥见的窗口(帮助原文强调它不受 umask 影响)。

Q5:一次能建多个目录吗?某个失败会影响其他吗? 能,空格分隔多个 DIRECTORY 即可(4.1 一次建三个);各参数独立处理,某个失败只报自己的错,不中断后续参数(3.2 三连报错与 3.5 报错+创建交替实测)。

Q6:-p 递归创建有没有层数上限? coreutils 不设人为层数,受文件系统路径长度限制(PATH_MAX 4096 字节)约束;3.3 实测三层 x/y/z,更深的路径同理逐层补齐,创建时每层权限按 umask 计算(-m 只管末级,见 3.4)。

六、参考链接