Suppose I have a directory /
, and it contains many directories /mydir
, /hisdir
, /herdir
, and each of those need to have a similar structure.
For each directory in /
, there needs to be a directory doc
and within it a file doc1.txt
.
One might naively assume they could execute
mkdir */doc
touch */doc/doc1.txt
but they would be wrong, because wildcards don't work like that.
Is there a way to do this without just making the structure once in an example then cp
ing it to the others?
And, if not, is there a way to do the above workaround without overwriting any existing files (suppose mydir
already contains the structure with some data I want to keep)?
EDIT: I'd also like to avoid using a script if possible.
Best Answer
With
zsh
:(/)
is a globbing qualifier,/
means to select only directories.$^array
(reminiscent ofrc
's^
operator) is to turn on a brace-like type of expansion on the array, so$^array/doc
is like{elt1,elt2,elt3}/doc
(whereelt1
,elt2
,elt3
are the elements of the array).One could also do:
Where
e
is another globbing qualifier that executes some given code on the file to select.With
rc
/es
/akanga
: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
: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
orbash
:${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), whiledir=(*(/))
(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 themkdir...
.