修改使用“find”找到的每个文件

发布于 2025-01-18 05:09:49 字数 433 浏览 0 评论 0原文

我有一个带有一堆.svg文件的文件夹。 我想以以下方式修改文件夹中的每个SVG文件:

  • 交换#000000使用currentColor
  • add class class 属于基于fileName的值(例如

find ./ -name \*.svg -exec sed -i '' -e "s/#000000/currentColor/g;s/<svg/<svg class=\"icon ${name}\"/g" {} +

​ 零件正常。

颜色替换 会非常感谢。

在Mac环境中工作

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 with currentColor
  • add class attribute with value based on filename (eg. for file named icon-super-cool.svg I want class="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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

我们的影子 2025-01-25 05:09:49

您的尝试存在几个问题:

  1. findexec 操作中,找到的文件的名称由 {} 表示,而不是 ${名称}
  2. 即使使用 {},类也会以 .svg 结尾,而不是您想要的。
  3. 即使使用 {},该类也将包含完整的文件路径 (./foo/bar/baz.svg),而不是您想要的。

以下假设您希望类名称为 icon-name,其中 name 是不带 .svg 扩展名的文件的基本名称:

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"' _ {} \;

或者,按照 Charles 的建议,减少 bash 运行的次数:

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' _ {} +

如果性能确实是一个问题,并且您希望一次处理多个文件({} + 而不是 {} \;< /code>),事情很困难sed 因为类替换字符串不是常量(虽然并非不可能,但这将是可怕的)。但 GNU awk 可以做到:

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}' {} +

第一个块 (BEGINFILE) 预处理每个文件名以构建类替换字符串,第二个块执行替换。这应该是最快的(未经测试)。

即使使用附带的 findsedbasenamebash 的默认版本,前两个解决方案也应该可以工作。 macOS。对于最后一个,您绝对需要最新版本的 GNU awk(请参阅 MacPorts 或 HomeBrew)。

There are several issues with your attempt:

  1. In the exec action of find the name of the found file is represented by {}, not ${name}.
  2. Even with {} the class will end with .svg, not what you want.
  3. 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).

清音悠歌 2025-01-25 05:09:49

您可以使用一个小脚本(例如,将例如script.sh):

#!/bin/bash
for path in "$@"; do
    sed -i "" -e "s/#3F505A/currentColor/g;s/<svg/<svg class=\"icon-$(basename -s ".svg" "${path}")\"/g" "${path}"
done

然后从查找以下调用它:

find . -name '*.svg' -exec ./script.sh {} +

You could use a small script (save e.g. as script.sh):

#!/bin/bash
for path in "$@"; do
    sed -i "" -e "s/#3F505A/currentColor/g;s/<svg/<svg class=\"icon-$(basename -s ".svg" "${path}")\"/g" "${path}"
done

and then call it from find like this:

find . -name '*.svg' -exec ./script.sh {} +
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文