如何在 bash 的每个子目录中创建相同的目录?

发布于 2025-01-10 20:40:17 字数 298 浏览 0 评论 0原文

我一直在尝试在“example”的所有子目录中创建目录“a”。

我尝试的是以下内容:

mkdir example/*/a

但它不将 '*' 作为通配符,返回 mkdir: 无法创建 «example/*/a» 目录: 它不存在文件或目录

请注意,我有太多示例中的子目录,所以我无法通过创建列表来做到这一点。

我不想用 for 循环来做到这一点,因为我正在学习 bash 并且不允许我使用循环。也许,没有办法避免 for 循环,在这种情况下,请告诉我:)。

谢谢。

I've been trying to create the directory "a" inside all the subdirectories of "example".

What I tried is the following:

mkdir example/*/a

But it doesn't take the '*' as a wildcard, returning mkdir: can not create «example/*/a» directory: It doesn't exist file or directory

Note that I have too much subdirectories in example, so I can't do it by creating a list.

I don't want to do it with for loops, because I'm learning bash and I'm not allowed to use loops. Probably, there is no way to avoid a for loop, in that case, please tell me :).

Thank you.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

べ繥欢鉨o。 2025-01-17 20:40:17

尝试:

dirs=( example/*/ )
mkdir -v "${dirs[@]/%/a}"
  • dirs=( example/*/ ) 创建一个包含 example 的所有子目录的数组 ( (example/dir1/ example/dir2/ ...))。
  • "${dirs[@]/%/a}" 扩展为包含 dirs 的所有元素的列表,并在每个元素后附加一个 a其中( (example/dir1/a example/dir2/a ...) )。

如果您有非常大量的子目录,上面代码中的mkdir可能会失败,并出现“参数列表太长”错误。请参阅rm、cp、mv 命令的参数列表太长错误

避免该问题的一种方法是将要创建的以 NUL 结尾的目录列表传递给 xargs -0:

dirs=( example/*/ )
printf '%s\0' "${dirs[@]/%/a}" | xargs -0 mkdir -v

如果需要,这将运行多个 mkdir 命令,每个都有一个不超过限制的参数列表。

但是,如果目录数量那么,您可能会遇到性能问题,因为 Bash (不必要但不可避免)对 example/*/ 生成的列表进行排序。在这种情况下,最好使用find。一种方法是:

find example -maxdepth 1 -mindepth 1 -type d -printf '%p/a\0' | xargs -0 mkdir -v

find 通过 -exec ... + 内置了对 xargs 行为的支持。然而,在这种情况下使用起来有点麻烦。我能很快想到的最好办法是:

find example -maxdepth 1 -mindepth 1 -type d    \
    -exec bash -c 'mkdir -v "${@/%//a}"' bash {} +

因为它在运行之前将 /a 添加到由 find 传递给 bash 的所有参数中mkdir 在它们上,它可能会遇到“参数列表太长”错误。我将其留在这里,因为它说明了一种有时有用的技术,但我建议不要使用它。

Try:

dirs=( example/*/ )
mkdir -v "${dirs[@]/%/a}"
  • dirs=( example/*/ ) creates an array of all the subdirectories of example ( (example/dir1/ example/dir2/ ...) ).
  • "${dirs[@]/%/a}" expands to a list containing all the elements of dirs with an a appended to each of them ( (example/dir1/a example/dir2/a ...) ).

If you have a very large number of subdirectories the mkdir in the code above may fail with an "Argument list too long" error. See Argument list too long error for rm, cp, mv commands.

One way to avoid the problem is to pass a NUL-terminated list of the directories to be created to xargs -0:

dirs=( example/*/ )
printf '%s\0' "${dirs[@]/%/a}" | xargs -0 mkdir -v

That will, if necessary, run multiple mkdir commands, each with an argument list that does not exceed the limit.

However, if the number of directories is that large you may run into performance problems due to Bash (unnecessarily, but unavoidably) sorting the list produced by example/*/). In that case it would be better to use find. One way to do it is:

find example -maxdepth 1 -mindepth 1 -type d -printf '%p/a\0' | xargs -0 mkdir -v

find has built-in support for xargs-like behaviour with -exec ... +. However, it's a bit fiddly to use in this case. The best I can come up with in a hurry is:

find example -maxdepth 1 -mindepth 1 -type d    \
    -exec bash -c 'mkdir -v "${@/%//a}"' bash {} +

Since it adds /a to all of the arguments passed to bash by find before running mkdir on them, it may encounter an "Argument list too long" error anyway. I'll leave it here because it illustrates a sometimes-useful technique, but I recommend against using it.

雪花飘飘的天空 2025-01-17 20:40:17

可能没有办法避免 for 循环

您可以使用 find

find example -type d -not -name a -exec mkdir -p {}/a \;

Probably, there is no way to avoid a for loop

You can use find:

find example -type d -not -name a -exec mkdir -p {}/a \;
め可乐爱微笑 2025-01-17 20:40:17

只是:

for i in example/*/; do
    mkdir "$i"/a
done

Just:

for i in example/*/; do
    mkdir "$i"/a
done
享受孤独 2025-01-17 20:40:17

我认为只有当您已经知道 example 下的子目录时,才能避免循环,例如:

mkdir example/{subdir1,subdir2,subdir3}/a

否则,请使用 for 循环来救援:

for d in example/*/; do mkdir "${d}a"; done

注意:添加 -vmkdir 如果您希望它显示创建的目录。

I think you can only avoid a loop if you already know the subdirectories under example, e.g.:

mkdir example/{subdir1,subdir2,subdir3}/a

Otherwise, use a for loop to the rescue:

for d in example/*/; do mkdir "${d}a"; done

Note: add a -v to mkdir if you want it to show you the directories that get created.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文