发布于 2026-01-06 0 阅读
0

使用 awk 批量重命名图像,包括图像分辨率

使用 awk 批量重命名图像,包括图像分辨率

我最近完成的“让我感觉很棒的极客小事”清单上,最新的一项是花了一小时完成的冒险,最终写出了这段代码:

$ file IMG* | awk 'BEGIN{a=0} {print substr($1, 1, length($1)-5),a++"_"substr($8,1, length($8)-1)}' | while read fn fr; do echo $(rename -v "s/$fn/img_$fr/g" *); done
IMG_20170808_172653_425.jpg renamed as img_0_4032x3024.jpg
IMG_20170808_173020_267.jpg renamed as img_1_3024x3506.jpg
IMG_20170808_173130_616.jpg renamed as img_2_3024x3779.jpg
IMG_20170808_173221_425.jpg renamed as img_3_3024x3780.jpg
IMG_20170808_173417_059.jpg renamed as img_4_2956x2980.jpg
IMG_20170808_173450_971.jpg renamed as img_5_3024x3024.jpg
IMG_20170808_173536_034.jpg renamed as img_6_4032x3024.jpg
IMG_20170808_173602_732.jpg renamed as img_7_1617x1617.jpg
IMG_20170808_173645_339.jpg renamed as img_8_3024x3780.jpg
IMG_20170909_170146_585.jpg renamed as img_9_3036x3036.jpg
IMG_20170911_211522_543.jpg renamed as img_10_3036x3036.jpg
IMG_20170913_071608_288.jpg renamed as img_11_2760x2760.jpg
IMG_20170913_073205_522.jpg renamed as img_12_2738x2738.jpg
// ... etc etc
Enter fullscreen mode Exit fullscreen mode

上述清单上的最后一项是“待办事项:为该清单拟一个更短的标题”。

我之前写过关于sed等命令行工具的强大功能。这篇文章将进一步阐述如何将所有这些神奇的功能串联起来,形成一条庞大、绵延、色彩斑斓、令人叹为观止的强大通道。

重命名文件

实际负责文件重命名的工具是,顾名思义,是rename。语法如下:rename -n "s/original_filename/new_filename/g" *其中-n`dry-run` 表示试运行,而替换操作-v会实际重命名文件。`- `s表示替换字符串,g`--global` 表示查找字符串的所有匹配项。`--matches` 表示*匹配零个或多个搜索替换参数。

我们稍后再讨论这个问题。

获取文件信息

当我$ file IMG_20170808_172653_425.jpg在图像目录中运行程序时,得到以下输出:

IMG_20170808_172653_425.jpg: JPEG image data, baseline, precision 8, 4032x3024, frames 3
Enter fullscreen mode Exit fullscreen mode

由于我们可以获得图像分辨率(如上所示的“4032x3024”),因此我们知道我们可以在新文件名中使用它。

提取我们想要的信息

我喜欢awk它的简洁性。它能处理多行文本,并通过内置变量将信息拆分成一个个独立的部分,我们可以用列号(例如 `<column>`、`<column>`$1等)来引用这些变量。$2默认情况下,awk它会根据空格分割列。以上面的例子为例:

1 2 3 4 5 6 7 8 9 10
IMG_20170808_172653_425.jpg: JPEG 图像 数据, 基线, 精确 8、 4032x3024, 框架 3

我们可以用不同的值来表示分隔符,例如,-F','如果我们想用逗号作为列分隔符。但对于我们当前的项目来说,空格就可以了。

在将信息填入新的文件名之前,我们需要解决几个问题。第一列$1包含我们想要的原始文件名,但末尾多了一个冒号“:”。我们也不需要“.jpg”。第二列$8还有一个多余的“,”,这也是我们不需要的。为了只提取我们需要的信息,我们将提取包含冒号的列的子字符串substr()

substr($1, 1, length($1)-5)- 这将给出从字符串开头到结尾的文件名,减去 5 个字符(“长度减 5”)。-
substr($8,1, length($8)-1)这将给出图像大小,去掉多余的逗号(“长度减 1”)。

避免重复文件名

为确保分辨率相同的两张图片不会产生相同且相互冲突的文件名,我们将在文件名后附加一个唯一的递增数字。

BEGIN{a=0}- 使用BEGINtell 指令awk确保以下代码只在开头(隆重介绍)运行一次。这里,我们声明变量a0。-
a++稍后在代码中,在文件名对应的位置,我们调用a并递增该变量。

awk打印字符串时,它会将除逗号分隔以外的所有部分连接起来。例如,{print a b c}`abc` 会生成“abc”, `ab c` 会生成“ab c”。{print a,b,c}

我们可以通过将下划线用引号括起来,向文件名中添加其他字符:"_"

把所有东西串联起来

要将一个命令的输出传递给另一个命令,我们使用“管道”,写作|.

如果只使用管道,所有来自 `file`file和`file` 的数据都会一次性awk输入,导致文件名非常非常长,而且可能无法编译。为了逐行运行命令行,我们可以使用 `push`和 `push` 。与 `push` 类似`push` 会接收输入并将其拆分成可以赋值和使用的变量。在我们的代码中,它从 `file` 中提取第一个输出(原始文件名),并将其赋值为变量名 `1` 。它提取第二个输出(递增的数字和图像分辨率),并将其赋值为变量名 `2`。变量名是任意的,你可以随意命名。renamerenamewhilereadawkreadawk$fn$fr

rename要像在终端中手动逐条输入命令一样运行这些命令,我​​们可以使用echo $(some command)。最后,循环done结束while

奖励环节:彩虹输出!

我说的“彩虹色”可不是开玩笑……

$ pip install lolcat
Enter fullscreen mode Exit fullscreen mode

以下是我们的完整代码:

$ file IMG* | awk 'BEGIN{a=0} {print substr($1, 1, length($1)-5),a++"_"substr($8,1, length($8)-1)}' | while read fn fs; do echo $(rename -v "s/$fn/img_$fs/g" *); done | lolcat
Enter fullscreen mode Exit fullscreen mode

享受!

文章来源:https://dev.to/victoria/batch-renaming-images-include-image-resolution-with-awk-2d7