Issue
I have a folder with a bunch of .svg
files.
I want to modify each svg file inside the folder in the following way:
- swap
#000000
withcurrentColor
- add
class
attribute with value based on filename (eg. for file namedicon-super-cool.svg
I wantclass="icon-super-cool"
here's where I've gotten to after hours of googling:
find ./ -name \*.svg -exec sed -i '' -e "s/#000000/currentColor/g;s/<svg/<svg class=\"icon ${name}\"/g" {} +
The colour replace part works fine. When it comes to the class attribute, every single icon get the same class attribute with ${name}
of the 1st file it processes.
Any help and explanation of what I am doing wrong would be much appreciated.
PS. working on a mac environment.
Solution
There are several issues with your attempt:
- In the
exec
action offind
the name of the found file is represented by{}
, not${name}
. - Even with
{}
the class will end with.svg
, not what you want. - Even with
{}
the class will contain the full file path (./foo/bar/baz.svg
), not what you want.
The following assumes you want the class name to be icon-name
where name
is the basename of the file without the .svg
extension:
find . -type f -name '*.svg' -exec bash -c \
'b=$(basename -s.svg "$1"); \
sed -i "" "s/#000000/currentColor/g;s/<svg/<svg class=\"icon-$b\"/g" "$1"' _ {} \;
Or, as suggested by Charles, to reduce the number of bash runs:
find . -type f -name '*.svg' -exec bash -c \
'for f in "$@"; do b=$(basename -s.svg "$f"); \
sed -i "" "s/#000000/currentColor/g;s/<svg/<svg class=\"icon-$b\"/g" "$f"; done' _ {} +
If performance is really an issue, and you want to process several files at once ({} +
instead of {} \;
), things are difficult with sed
because the class replacement string is not constant (not impossible, though, but this would be horrible). But GNU awk
can make it:
find . -type f -name '*.svg' -exec awk -i inplace '\
BEGINFILE {s=gensub(/^(.*\/)?(.*)\.svg$/,"<svg class=\"icon-\\2\"",1,FILENAME)} \
{gsub(/#000000/,"currentColor"); gsub(/<svg/,s); print}' {} +
The first block (BEGINFILE
) preprocesses each file name to build the class replacement string and the second performs the replacements. This should be the fastest of all (not tested).
The two first solutions should work even with the default versions of find
, sed
, basename
and bash
that come with macOS. For the last one you absolutely need a decently recent version of GNU awk
(see MacPorts or HomeBrew).
Answered By - Renaud Pacalet Answer Checked By - Marie Seifert (WPSolving Admin)