With zsh
:
dirs=(*(/))
mkdir -- $^dirs/doc
touch -- $^dirs/doc/doc1.txt
(/)
is a globbing qualifier, /
means to select only directories.
$^array
(reminiscent of rc
's ^
operator) is to turn on a brace-like type of expansion on the array, so $^array/doc
is like {elt1,elt2,elt3}/doc
(where elt1
, elt2
, elt3
are the elements of the array).
One could also do:
mkdir -- *(/e:REPLY+=/doc:)
touch -- */doc(/e:REPLY+=/doc1.txt:)
Where e
is another globbing qualifier that executes some given code on the file to select.
With rc
/es
/akanga
:
dirs = */
mkdir -- $dirs^doc
touch -- $dirs^doc/doc1.txt
That's using the ^
operator which is like an enhanced concatenation operator.
rc
doesn't support globbing qualifiers (which is a zsh-only feature). */
expands to all the directories and symlinks to directories, with /
appended.
With tcsh
:
set dirs = */
mkdir -- $dirs:gs:/:/doc::q
touch -- $dirs:gs:/:/doc/doc1.txt::q
The :x
are history modifiers that can also be applied to variable expansions. :gs
is for global substitute. :q
quotes the words to avoid problems with some characters.
With zsh
or bash
:
dirs=(*/)
mkdir -- "${dirs[@]/%/doc}"
touch -- "${dirs[@]/%/doc/doc1.txt}"
${var/pattern/replace}
is the substitute operator in Korn-like shells. With ${array[@]/pattern/replace}
, it's applied to each element of the array. %
there means at the end.
Various considerations:
dirs=(*/)
includes directories and symlinks to directories (and there's no way to exclude symlinks other than using [ -L "$file" ]
in a loop), while dir=(*(/))
(zsh extension) only includes directories (dir=(*(-/))
to include symlinks to directories without adding the trailing slash).
They exclude hidden dirs. Each shell has specific option to include hidden files).
If the current directory is writable by others, you potentially have security problems. As one could create a symlink there to cause you to create dirs or files where you would not want to. Even with solutions that don't consider symlinks, there's still a race condition as one may be able to replace a directory with a symlink in between the dirs=(*/)
and the mkdir...
.
find . -maxdepth 1
,-execdir
is the same as-exec
– Stéphane Chazelas Aug 05 '14 at 07:45-exec
. It's also the case that the depth options might not be needed at all in the specific scenario needed — could be justfind *
with the-depth
option. (But they're good to generally be comfortable with!) – mattdm Aug 05 '14 at 07:47-maxdepth
,-mindepth
,-execdir
or embedding{}
in an argument is standard/portable. And while-execdir
generally improves security/reliability, in this very case, it doesn't remove the race condition. Also note that it will not skip hidden dirs. – Stéphane Chazelas Aug 05 '14 at 08:50