bash 脚本根据计算重命名文件

发布于 2024-11-07 11:19:19 字数 543 浏览 0 评论 0原文

我有一个包含 PNG 图像的文件系统。文件系统的布局为:ZOOM/X/Y.png,其中 ZOOM、X 和 Y 均为整数。

我需要更改 PNG 文件的名称。基本上,我需要将 Y 从当前值转换为 2^ZOOM-Y-1。我编写了一个 bash 脚本来完成此任务。不过,我怀疑它可以大幅优化。 (我还怀疑用 Perl 编写它可能会更好,但那是另一个故事了。)

这是脚本。这已经是最好的结果了吗?或者性能可以优化吗?我可以使用哪些工具来分析脚本并告诉我所有执行时间都花在哪里了?

#!/bin/bash

tiles=`ls -d */*/*`

for oldPath in $tiles
do
   oldY=`basename -s .png $oldPath`
   zoomX=`dirname $oldPath`
   zoom=`echo $zoomX | sed 's#\([^\]\)/.*#\1#'`
   newY=`echo 2^$zoom-$oldY-1|bc`  
   mv ${zoomX}/${oldY}.png ${zoomX}/${newY}.png
done

I have a file system containing PNG images. The layout of the filesystem is: ZOOM/X/Y.png where ZOOM, X, and Y are all integers.

I need to change the names of the PNG files. Basically, I need to convert Y from its current value to 2^ZOOM-Y-1. I've written a bash script to accomplish this task. However, I suspect it can be optimized substantially. (I also suspect that I may have been better off writing it in Perl, but that is another story.)

Here is the script. Is this about as good as it gets? Or can the performance be optimized? Are there tools I can use that would profile the script for me and tell me where I'm spending all my execution time?

#!/bin/bash

tiles=`ls -d */*/*`

for oldPath in $tiles
do
   oldY=`basename -s .png $oldPath`
   zoomX=`dirname $oldPath`
   zoom=`echo $zoomX | sed 's#\([^\]\)/.*#\1#'`
   newY=`echo 2^$zoom-$oldY-1|bc`  
   mv ${zoomX}/${oldY}.png ${zoomX}/${newY}.png
done

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

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

发布评论

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

评论(5

安稳善良 2024-11-14 11:19:20

由于对公式和更新的变量名称的误解而重写。除了 mvls 之外仍然没有子进程。

#!/bin/bash

tiles=`ls -d */*/*`

for thisPath in $tiles
do
   thisFile=${thisPath#*/*/}
   oldY=${thisFile%.png}
   zoomX=${thisPath%/*}
   zoom=${thisPath%/*/*}
   newY=$(((1<<zoom) - oldY - 1))
   mv ${zoomX}/${oldY}.png ${zoomX}/${newY}.png
done

REWRITE due to misunderstanding of the formula and the updated var names. Still no subprocesses apart from mv and ls.

#!/bin/bash

tiles=`ls -d */*/*`

for thisPath in $tiles
do
   thisFile=${thisPath#*/*/}
   oldY=${thisFile%.png}
   zoomX=${thisPath%/*}
   zoom=${thisPath%/*/*}
   newY=$(((1<<zoom) - oldY - 1))
   mv ${zoomX}/${oldY}.png ${zoomX}/${newY}.png
done
原来分手还会想你 2024-11-14 11:19:20

重命名的总体吞吐量可能受到文件系统的限制。选择正确的文件系统并针对此类操作对其进行调整将比调整脚本更快地加快整体工作的速度。

如果优化脚本,您可能会看到 CPU 消耗更少,但总持续时间相同。由于分叉各种子进程(basenamedirnamesedbc)可能比实际的更重要你可能是对的,perl 实现会使用更少的 CPU,因为它可以在内部执行所有这些操作(包括 mv)。

It's likely that the overall throughput of your rename is limited by the filesystem. Choosing the right filesystem and tuning it for this sort of operation would speed up the overall job much more than tweaking the script.

If you optimize the script you'll probably see less CPU consumed but the same total duration. Since forking off the various subprocesses (basename, dirname, sed, bc) are probably more significant than the actual work you are probably right that a perl implementation would use less CPU because it can do all of those operations internally (including the mv).

笑梦风尘 2024-11-14 11:19:20

如果这是我的脚本,我会做 3 项改进。它们是否会产生巨大的影响——我不这么认为。

但您应该避免解析 ls 的输出。也许这个目录是非常可预测的,从里面发现的东西来看,但是如果我正确地阅读了你的脚本,你可以直接使用 for 的通配符:

for thisPath in */*/*

重复地, $(cmd) 比 cmd 与不推荐使用的更好反引号,不可嵌套。

thisDir=$(dirname $thisPath)

直接在 bash 中进行算术:

newTile=$((2**$zoom-$thisTile-1))

只要不需要浮点,否则输出会变得太大。

我不明白 sed 部分:

zoom=`echo $zoomX | sed 's#\([^\]\)/.*#\1#'`

反斜杠后是否缺少某些内容?第二个?您正在寻找不是反斜杠、后跟斜杠的东西吗?也许也可以纯粹用 bash 来完成。

I see 3 improvements I would do, if it was my script. Whether they have an huge impact - I don't think so.

But you should avoid as hell parsing the output of ls. Maybe this directory is very predictable, from the things found inside, but if I read your script correctly, you can use the globbing with for directly:

for thisPath in */*/*

repeatedly, $(cmd) is better than cmd with the deprecated backticks, which aren't nestable.

thisDir=$(dirname $thisPath)

arithmetic in bash directly:

newTile=$((2**$zoom-$thisTile-1))

as long as you don't need floating point, or output is getting too big.

I don't get the sed-part:

zoom=`echo $zoomX | sed 's#\([^\]\)/.*#\1#'`

Is there something missing after the backslash? A second one? You're searching for something which isn't a backslash, followed by a slash-something? Maybe it could be done purely in bash too.

幸福%小乖 2024-11-14 11:19:20

Donald Knuth 的计算准则之一是“不要过早优化”。脚本运行得非常快,“mv”操作(只要它们不跨文件系统,您实际上将其复制到另一个磁盘,然后删除文件)也非常快,因为所有文件系统都必须在大多数情况只是重命名文件或更改其来源。
可能它大部分时间都花在最初的“ls”操作上。我怀疑你有很多文件。那里没什么可做的。使用 Perl 或 Python 等其他语言也会面临同样的障碍。然而,您也许能够获得更多智力,而不是将自己限制在 3 个级别(//*)。

one precept of computing credited to Donald Knuth is, "don't optimize too early." Scripts run pretty fast and 'mv' operations(as long as they're not going across filesystems where you're really copying it to another disk and then deleting the file) are pretty fast as well, as all the filesystem has to do in most cases is just rename the file or change its parentage.
Probably where it's spending most of its time is in that intial 'ls' operation. I suspect you have ALOT of files. There isn't much that can be done there. Doing it another language like perl or python is going to face the same hurdle. However you might be able to get more INTELLIGENCE and not limit yourself to 3 levels(//*).

最丧也最甜 2024-11-14 11:19:19
for oldpath in */*/*
do
    x=$(basename "$oldpath" .png)
    zoom_y=$(dirname "$oldpath")
    y=$(basename "$zoom_y")
    ozoom=$(dirname "$zoom_y")
    nzoom=$(echo "2^$zoom-$y-1" | bc)
    mv "$oldpath" $nzoom/$y/$x.png
done

这可以避免使用 sed。我喜欢 basenamedirname。不过,您也可以使用 bash(和 Korn)shell 表示法,例如:

y=${zoom_y#*/}
ozoom=${zoom_y%/*}

您也许根本不需要调用 basenamedirname 就能完成这一切。

for oldpath in */*/*
do
    x=$(basename "$oldpath" .png)
    zoom_y=$(dirname "$oldpath")
    y=$(basename "$zoom_y")
    ozoom=$(dirname "$zoom_y")
    nzoom=$(echo "2^$zoom-$y-1" | bc)
    mv "$oldpath" $nzoom/$y/$x.png
done

This avoids using sed. I like basename and dirname. However, you can also use bash (and Korn) shell notations such as:

y=${zoom_y#*/}
ozoom=${zoom_y%/*}

You might be able to do it all without invoking basename or dirname at all.

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