My recomended solutions:
find . -mindepth 1 -maxdepth 1 -type d '(' -exec mkdir -- '{}'/pictures \; -o -exec printf 'Could not create: [[%s/pictures]] ??\n' '{}' \; ')';
or
(for d in ./* ; do [ -d "$d" ] && { mkdir -- "$d"/pictures || printf 'Could not create [[%s/pictures]]... permissions problem, disk is full?\n' "$d";};done;);
or
(for d in * ; do [ -d "$d" ] && { mkdir -- "$d"/pictures || printf 'Could not create [[%s/pictures]]... permissions problem, disk is full?\n' "$d";};done;);
The following is an example:
(for d in ./* ; do [ -d "$d" ] && { mkdir "$d"/pictures || printf 'Could not create [[%s/pictures]]... permissions problem, disk is full?\n' "$d";};done;);
This last one will work, but i don't recommend it, it is here to show how using ./*
instead of *
can help reduce risks in some cases as the expansions for ./*
will be the same as for *
but prefixed with ./
so it they are valid paths also and even if any of those values is used carelessly as in mkdir "$d"/pictures
, it will cause no problems (or less problems at least, depending on the context).
All of them will work with names containing
(space), tabs, CR, LF... ANY CHARACTER in names (except /
, and that's because it's not allowed in names, only to separate one name from the other in the path, and as root directory ). So basically, it will work with any path.
To every one that have read the answers that uses variables for file system names: don't follow those examples, at the time of writing all are wrong, and there is a common problem in all of them: the variables are not quoted but in all cases here they should. (If there isn't any problematic character in the names, it will do the same, but even in that case it's good practice to quote them).
But this does not apply only to variables containing file system names, every single variable substitution should be quoted when possible.
There are very few circumstances in which one needs not to quote a shell variable; and in all of them variable contents should be triple-checked, in that situations you can't be too careful. Those circumstances are very rare and can be avoided almost always.
There is a exception to this: Here-documents, substitutions inside them behave like they are already quoted, substitutions inside substitutions inside here-documents behave as normal.
(*) I've already seen this particular cancer spread enough, and too many people asking why does a command break only in some cases/paths... and being 'helped' by rewriting half of the script when a pair of "
would have fixed the offending line.
I think i'm gonna get 'I quote vars and substitutions like there's no tomorrow!' printed on a t-shirt.).
At the time of writing, and IMHO there is not a single acceptable (acceptable without objections) answer to the question, and that's unacceptable!
In the last line of the question, OP asked how to mkdir */pictures
and i take that as a petition for a generic solution that does not make assumptions on names of subdirectories.
The second code block from the answer by Nelson ( mkdir {1..777}/pictures;
) works and doesn't contain any errors nor bad practices (if we don't count the forcing of the use of bash as one xD), but will only work in the EXACT scenario described in the first part of the question and only in bash or some other shell implementing {n..m}
brace expansion for sequence-based generation of multiple args from one. The first code block in that answer only deserves to be ignored, it is awfully wrong.
The one by mdpc, edited by Gareth is quite acceptable, almost perfect :
find . -mindepth 1 -maxdepth 1 -type d -exec mkdir {}/pictures \;
despite the fact that using it as-is could end in massacre; but it can be made perfect by modifying it so it looks like:
find . -mindepth 1 -maxdepth 1 -type d -exec mkdir -- '{}'/pictures \;
(It is the first in the list of solutions in my anwer).
It includes --
between the options (flags) for mkdir
(or mkdir
itself) and the argument:
It's good practice to always do that when the start character of the first argument is not hardcoded into the command to keep it from trying to parse the argument as a potential option(flag). This can be done with almost all commands (there are a few exceptions, find itself is an obvious one).
Note that i quoted {}
, its more correct to use '{}'
, or \{\}
, since that way it won't have any special meaning for any posix shell even crappy ones.
In short: only two solutions don't contain errors, but one uses a "bashism" so won't work in many shells, and the other could have been more correct (not good enough for the people to correctly learn script-fu from), quite disappointing. I had too high expectations i guess...
I'm not saying that no answer will work for THAT EXACT scenario, most will, but definitely most of them aren't correct code (i am not referring to syntax, not only at least) and/or include bad practices of some kind (some of them even real atrocities).
Sources: A kind of obsession about standards and correctness of code, and documentation from http://www.opengroup.org/, man dash, man bash and even the internet deeps! : but trusted sources, not answers from dont-even-know-how-to-quote-correctly-guys... (there are at least couple of answers that looks like that in this question, no offense intended, no one is born knowing everything).
bash
scripting count as programming?