I'm looking to copy files from subdirectories that match this pattern
vendor/plugin/*/tasks/*.rake
into a folder
lib/tasks
Sounds pretty easy:
cp vendor/plugin/*/tasks/*.rake lib/tasks
Or if the first *
should match a whole subtree, use something like:
find vendor/plugin -path "*/tasks/*.rake" -exec cp "{}" lib/tasks +
-exec cp {} arg +
that way. With +
, {}
has to be the last argument. So -exec sh -c 'exec cp "$@" lib/tasks' sh {} +
Mar 20, 2019 at 12:40
find
, both *
will match any number of subdirectories, so it would match on vendor/plugin/a/b/c/tasks/e/f/g/h.rake
for instance.
Mar 20, 2019 at 12:42
Assuming you want to handle name collisions (for example, the collision that would occur between vendor/plugin/a/tasks/1.rake
and vendor/plugin/b/tasks/1.rake
) by being notified about them instead of overwriting files, then use a shell loop:
destdir=lib/tasks
for pathname in vendor/plugin/*/tasks/*.rake
do
destpath=$destdir/${pathname##*/}
if [ -e "$destpath" ]; then
printf 'Can not move "%s", "%s" is in the way' \
"$pathname" "$destpath" >&2
continue
fi
cp "$pathname" "$destpath"
done
The line
destpath=$destdir/${pathname##*/}
could also be written as
destpath=$destdir/$(basename "$pathname")
and simply constructs the pathname for the destination for the sake of checking whether it's already taken.
You could also just do
cp -i vendor/plugin/*/tasks/*.rake lib/tasks
to get an interactive prompt for each name collision from the cp
utility itself. The command relies on expanding the vendor/plugin/*/tasks/*.rake
pattern on the command line, and depending on how many pathnames that expands to, it may potentially trigger a "argument list too long" error, in which case a loop may be used instead:
for pathname in vendor/plugin/*/tasks/*.rake
do
cp -i "$pathname" lib/tasks
done
This loop is pretty much identical to the initial loop in this answer. The only difference is that we let the cp
utility prompt the user whenever there is a name collision.
All variations above assume that the pattern vendor/plugin/*/tasks/*.rake
actually matches something and that the destination directory lib/tasks
already exists. I also assume that you are not interested in subdirectories or files with hidden names.