mkdir 命令详解与参数实测(Ubuntu 22.04)
mkdir 命令逐参数实测详解:默认权限与 umask、-p 递归创建与幂等语义、-m 创建时设权、-v 冗余输出、父目录缺失与目录已存在的报错回显与退出码,全部命令与回显在 Ubuntu 22.04(GNU coreutils 8.32)实测通过。
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)。
六、参考链接
- GNU coreutils 官方手册(mkdir 章节):https://www.gnu.org/software/coreutils/manual/html_node/mkdir-invocation.html
- 在线文档:https://www.gnu.org/software/coreutils/mkdir
- umask 机制:本机执行
man bash搜 umask,或help umask(Ubuntu 22.04 内置) - 本机帮助:
mkdir --help、man mkdir、info '(coreutils) mkdir invocation'