如何在 bash 中的每个子目录中创建相同的目录?
How do I create the same directory in every subdirectories in bash?
我一直在尝试在“example”的所有子目录中创建目录“a”。
我试过的是:
mkdir example/*/a
但是它没有把'*'作为通配符,返回mkdir: cannot create «example/*/a» directory: It doesn't exist file or directory
注意我例子中的子目录太多,无法通过创建列表来实现
我不想用 for 循环来做,因为我正在学习 bash 并且不允许我使用循环。可能无法避免 for 循环,如果是这样,请告诉我 :).
谢谢。
Probably, there is no way to avoid a for loop
您可以使用 find
:
find example -type d -not -name a -exec mkdir -p {}/a \;
刚刚:
for i in example/*/; do
mkdir "$i"/a
done
我认为只有知道example
下的子目录才能避免循环,例如:
mkdir example/{subdir1,subdir2,subdir3}/a
否则,使用 for 循环来拯救:
for d in example/*/; do mkdir "${d}a"; done
注意:如果您想让 mkdir
显示已创建的目录,请将 -v
添加到 mkdir
。
尝试:
dirs=( example/*/ )
mkdir -v "${dirs[@]/%/a}"
dirs=( example/*/ )
创建一个包含 example
( (example/dir1/ example/dir2/ ...)
) 的所有子目录的数组。
"${dirs[@]/%/a}"
扩展为包含 dirs
的所有元素的列表,每个元素都附加了 a
( (example/dir1/a example/dir2/a ...)
)。
如果您有非常 的大量子目录,上述代码中的mkdir
可能会失败并出现“参数列表太长”错误。参见 Argument list too long error for rm, cp, mv commands。
避免该问题的一种方法是将要创建的目录的 NUL-terminated 列表传递给 xargs -0
:
dirs=( example/*/ )
printf '%s[=11=]' "${dirs[@]/%/a}" | xargs -0 mkdir -v
这将在必要时 运行 多个 mkdir
命令,每个命令都有一个不超过限制的参数列表。
但是,如果目录数量 大,您可能 运行 由于 Bash(不必要但不可避免地)对目录进行排序而导致性能问题example/*/
生成的列表)。在那种情况下,使用 find
会更好。一种方法是:
find example -maxdepth 1 -mindepth 1 -type d -printf '%p/a[=12=]' | xargs -0 mkdir -v
find
built-in 支持与 -exec ... +
类似 xargs
的行为。但是,在这种情况下使用起来有点麻烦。我能想到的最好的是:
find example -maxdepth 1 -mindepth 1 -type d \
-exec bash -c 'mkdir -v "${@/%//a}"' bash {} +
因为它在 运行 宁 mkdir
之前将 /a
添加到 find
传递给 bash
的所有参数,它可能会遇到一个无论如何都会出现“参数列表太长”错误。我会把它留在这里,因为它说明了一种 sometimes-useful 技术,但我建议不要使用它。
我一直在尝试在“example”的所有子目录中创建目录“a”。
我试过的是:
mkdir example/*/a
但是它没有把'*'作为通配符,返回mkdir: cannot create «example/*/a» directory: It doesn't exist file or directory
注意我例子中的子目录太多,无法通过创建列表来实现
我不想用 for 循环来做,因为我正在学习 bash 并且不允许我使用循环。可能无法避免 for 循环,如果是这样,请告诉我 :).
谢谢。
Probably, there is no way to avoid a for loop
您可以使用 find
:
find example -type d -not -name a -exec mkdir -p {}/a \;
刚刚:
for i in example/*/; do
mkdir "$i"/a
done
我认为只有知道example
下的子目录才能避免循环,例如:
mkdir example/{subdir1,subdir2,subdir3}/a
否则,使用 for 循环来拯救:
for d in example/*/; do mkdir "${d}a"; done
注意:如果您想让 mkdir
显示已创建的目录,请将 -v
添加到 mkdir
。
尝试:
dirs=( example/*/ )
mkdir -v "${dirs[@]/%/a}"
dirs=( example/*/ )
创建一个包含example
((example/dir1/ example/dir2/ ...)
) 的所有子目录的数组。"${dirs[@]/%/a}"
扩展为包含dirs
的所有元素的列表,每个元素都附加了a
((example/dir1/a example/dir2/a ...)
)。
如果您有非常 的大量子目录,上述代码中的mkdir
可能会失败并出现“参数列表太长”错误。参见 Argument list too long error for rm, cp, mv commands。
避免该问题的一种方法是将要创建的目录的 NUL-terminated 列表传递给 xargs -0
:
dirs=( example/*/ )
printf '%s[=11=]' "${dirs[@]/%/a}" | xargs -0 mkdir -v
这将在必要时 运行 多个 mkdir
命令,每个命令都有一个不超过限制的参数列表。
但是,如果目录数量 大,您可能 运行 由于 Bash(不必要但不可避免地)对目录进行排序而导致性能问题example/*/
生成的列表)。在那种情况下,使用 find
会更好。一种方法是:
find example -maxdepth 1 -mindepth 1 -type d -printf '%p/a[=12=]' | xargs -0 mkdir -v
find
built-in 支持与 -exec ... +
类似 xargs
的行为。但是,在这种情况下使用起来有点麻烦。我能想到的最好的是:
find example -maxdepth 1 -mindepth 1 -type d \
-exec bash -c 'mkdir -v "${@/%//a}"' bash {} +
因为它在 运行 宁 mkdir
之前将 /a
添加到 find
传递给 bash
的所有参数,它可能会遇到一个无论如何都会出现“参数列表太长”错误。我会把它留在这里,因为它说明了一种 sometimes-useful 技术,但我建议不要使用它。