Bash大括号展开操作数行为疑问:cp与mkdir命令表现差异解析请求
Bash大括号展开在mkdir与cp中的行为差异原因
现象对比
正常工作的mkdir命令
执行mkdir -p {folder1,folder2,folder3}/{folderA,folderB,folderC}时,会生成预期的嵌套目录结构:
$ tree . . ├── folder1 │ ├── folderA │ ├── folderB │ └── folderC ├── folder2 │ ├── folderA │ ├── folderB │ └── folderC └── folder3 ├── folderA ├── folderB └── folderC
不符合预期的cp命令
执行cp -r folder1/ folder2/{folderA,folderB}时,并未将folder1/分别复制到folder2/folderA和folder2/folderB,而是把folder2/folderA当作第二个源目录,最终将两个源都复制到folder2/folderB下,结构如下:
. ├── folder1 │ ├── folderA │ ├── folderB │ └── folderC ├── folder2 │ ├── folderA │ ├── folderB │ │ ├── folder1 │ │ │ ├── folderA │ │ │ ├── folderB │ │ │ └── folderC │ │ └── folderA │ └── folderC └── folder3 ├── folderA ├── folderB └── folderC
核心原因
Bash的大括号展开只是生成所有可能的参数组合,不会自动拆分出多条命令,最终行为完全取决于具体命令的参数解析规则:
- mkdir的参数逻辑适配展开结果
mkdir -p接受任意数量的路径参数,每个参数都是独立的创建目标。大括号展开后,命令会变成:
mkdir -p folder1/folderA folder1/folderB folder1/folderC folder2/folderA folder2/folderB folder2/folderC folder3/folderA folder3/folderB folder3/folderC
所有展开后的路径都会被mkdir依次创建,自然符合预期。
- cp的参数规则限制了这种用法
cp的参数逻辑是:最后一个参数为目标路径,前面所有参数都是要复制的源。当cp -r folder1/ folder2/{folderA,folderB}展开后,实际执行的是:
cp -r folder1/ folder2/folderA folder2/folderB
此时cp会把folder1/和folder2/folderA视为两个源,folder2/folderB视为唯一目标,所以会把两个源都复制到folder2/folderB目录下,这就是你看到的异常结果。
实现预期效果的方法
如果要把folder1/分别复制到两个目标路径,需要让Bash生成两条独立的cp命令,常见方法有:
- 使用for循环遍历目标路径:
for dest in folder2/{folderA,folderB}; do cp -r folder1/ "$dest" done
- 直接写两条命令(或用大括号简化写法):
cp -r folder1/ folder2/folderA; cp -r folder1/ folder2/folderB # 或者用大括号包裹,保持逻辑关联 { cp -r folder1/ folder2/folderA; cp -r folder1/ folder2/folderB; }
- 用xargs配合路径替换:
echo folder2/{folderA,folderB} | xargs -I {} cp -r folder1/ {}
内容的提问来源于stack exchange,提问作者Jay
相关产品推荐
相关产品推荐

