跳转至内容

Sort images by resolution

来自 ArchWiki
注意 为了加快访问已恢复或已修复文件的速度,您可以使用 shake 工具进行碎片整理。

当文件恢复完成后,并且您使用 恢复后任务 脚本恢复了图像,那么按分辨率对图像进行排序可能会很有用。这将有助于将您拍摄的照片、网络摄像头图像或任何其他图像按分辨率分类到不同的文件夹中,因为大多数它们通常使用相同的相关图像分辨率。

收集图像信息

警告 在运行脚本之前,您必须安装 feh 程序。
注意 为了加快收集图像信息的速度,您可以通过使用 非重复文件 列表来跳过重复的图像,但您也需要在此脚本中删除 MIME 类型检查,并改为添加按扩展名检查文件的功能。
collect-info-about-images.sh
#!/bin/bash
if [ 'XX' != 'XX'"$1" ]; then 
 if [ -f "$1"  ]; then
# mime part start
  IsIt=$(file "$1" --mime-type -b);
  NeedImageOnly="ItIs_"${IsIt/'/'*/}
   if [ "$NeedImageOnly" == "ItIs_image" ] ; then
# mime part end
ImageInfoFEH=($(feh -l "$1"))
IfDamaged=${?}
ImageType=${ImageInfoFEH[9]}
   Height=${ImageInfoFEH[11]}
    Width=${ImageInfoFEH[10]}
   if [ "$IfDamaged" != '0'  ]; then 
    echo "$1" "Damaged" "${IfDamaged}";
   fi;
    echo "$1"'|'W'|'$Width'|'H'|'$Height'|'Format'|'$ImageType'|'Errors'|'$IfDamaged'|' >> collect-info-about-images.txt
# mime part start
  fi
# mime part end
   else
    echo The « "$1" » is not a valid file name.
  fi
 else
  ScriptsName=${0##*/}
   find -type f -exec sh -e "./$ScriptsName" "{}" \;
  #find -type f  -name "*.jpg" -o -name "*.gif" -o -name "*.png" -exec sh -e "./$ScriptsName" "{}" \;
fi

$IfDamaged 变量包含 feh 返回的退出状态码。

  • feh 程序会忽略图像中的一些错误,例如像素数据错误,只要它包含足够的可读视觉数据以显示即可。
  • 像素错误会导致图像的一部分或整个图像无法正确显示,它会导致错误的颜色或空白/空区域,这通常会使图像或多或少无用,这在很大程度上取决于损坏数据在其中的数量。

您还可以安装 pngcheckAUR 来检查 "PNG, JNG 或 MNG" 的完整性,以及/或 jpeginfoAUR,并使用错误输出中的 $IfDamaged 变量,或者修改脚本以跳过将损坏的文件添加到 collect-info-about-images.txt 文件中。

pngcheckAUR 检查结果示例

./f939799496.png  invalid IDAT row-filter type (11)
./f939799496.png  private (invalid?) IDAT row-filter type (236) (warning)
./f939799496.png  private (invalid?) IDAT row-filter type (231) (warning)
./f939799496.png  invalid IDAT row-filter type (49)
./f939799496.png  zlib: inflate error = -3 (data error)
ERROR: ./f939799496.png
OK: ./f218842888.png (532x552, 32-bit RGB+alpha, non-interlaced, 95.8%).

jpeginfoAUR 检查结果示例

f62152912.jpg 5678 x 2829 24bit Exif  N 11625509  Corrupt JPEG data: 1074 extraneous bytes before marker 0xd9  [WARNING]
f124619744.jpg  144 x 119  24bit JFIF  N    5813  [OK]
注意 jpeginfoAUR 工具无法递归扫描目录,但可以从 `find -type f -name "*.jpg">>FileWithPathTo-images.txt` 创建的文件中读取文件名,计算它们的 md5sums,并有一个选项可以移除损坏的图像文件。

要从脚本中的字符串中提取必要数据,最好使用 表达式 而不是外部程序,例如 sedgawk,以使脚本运行得更快一些,例如

AA="$(jpeginfo -c f62152912.jpg)";
ZZ="${AA/*' [OK]'/}"; 

if [ 'XX'"$ZZ" == 'XX' ]; then 
  echo File is good'!!!';
fi

collect-info-about-images.sh 脚本按模式生成图像数据

full path to image|Width|size|Height|size|Format|type of image|Errors|exit code by feh|

示例: Images/f269351998.bmp|W|40|H|39|Format|bmp|Errors|0|

Sort images by resolution

此脚本根据分辨率创建文件夹。您可以设置每个文件夹中文件的最大数量以及在一个基本文件类型命名的文件夹中有多少个子目录。当达到限制时,将向文件夹名称添加一个按顺序递增的数字来创建新文件夹。如果您有大量文件,并且不想让一个文件夹过载,那么您还可以在基本目标变量 IfExist="${Destination}/ 之后添加自己的计数器来创建新子文件夹,只需注意确保整个目标路径的开头和结尾都有引号。将文件夹中的图像数量限制在一个范围内,通常更容易浏览文件夹,缩略图加载速度更快,并且更容易记住或收藏文件夹编号/名称,而不是试图在可能包含成千上万张图像的拥挤文件夹中再次找到同一张图像。

警告
  • 这些脚本仅为示例,在使用前必须根据您的需求进行修改,请小心!
  • 只有当您确认路径已正确创建且从源文件中读取变量没有问题后,才删除 echo 命令,尤其是在您已将自己的选项添加到 collect-info-about-images.sh 文件以收集、存储甚至更多图像信息的情况下。
  • 您必须删除 mkdirmv 前面的 echo 命令。
  • 屏幕上的任何输出都会减慢脚本速度,为了使其更快,可以通过删除 -v 选项来禁用 mvcp 的详细输出。
  • 要监控脚本的运行,您可以使用 CPU 监视器工具并列出目标目录中的文件夹。或者,仅在那些可以最大程度地减少输出的脚本部分添加 echo 命令,例如,用于更新文件夹编号的计数器部分,以避免无休止的时间感。
  • 您也可以用 cp 命令替换 mv 命令,以复制文件而不是移动它们。
#!/bin/bash

NumberOfBaseDir="0"
SubDirNumber="0"
CountAll="0"
NumDir="0"

echo Creating destination.
Destination="./SortedImages"
echo mkdir -v "${Destination}" -p 
echo Created destination with status: $?

echo Your set of limitations.
SDN=50; echo Limit files in a subdir: $SDN
NBD=50; echo Limit subdirs in a file type named destination: $NBD

SourceDataFile="collect-info-about-images.txt"
echo Source file with a necessery data: $SourceDataFile

if [ 'XX' == 'XX'"$SourceDataFile" ] ; then 
 echo The '$SourceDataFile' variable is empty
 exit 1
else 
 if [ ! -f "$SourceDataFile" ]; then 
  echo The "$SourceDataFile" file doesn"'"t exist
  exit 2
 fi;
fi;

echo Populating an array from a file
ArrayFillCount=0;
while read line ; do
  tmpWb="${line/|H|*/}";
W="${tmpWb/*W|/}";
  tmpHb="${line/|Format|*/}";
H="${tmpHb/*|/}";

#if (( "$W" >= "800" )) && (( "$W" <=  "1000" )); then
#if (( "$H" >= "800" )) && (( "$H" <=  "1000" )); then
  ArrayOfFiles[$ArrayFillCount]="$line";
  ArrayFillCount=$((ArrayFillCount+1))
DupLimitKeeper[$W,$H]="0";
#fi;fi;

done < $SourceDataFile;
echo Done with extracting of necessary data about resolutions.

echo Starting loop of restoration
XX=${#ArrayOfFiles[@]}
while [  "${XX}" != "${CountAl}l" ] ; do
  preType=${ArrayOfFiles[$CountAll]/*"|Format|"/};
ImageType=${preType/|*/}
  preW=${ArrayOfFiles[$CountAll]/*"|W|"/};Width=${preW/|*/};preH=${ArrayOfFiles[$CountAll]/*"|H|"/} 
Height=${preH/|*/};
PathToFile=${ArrayOfFiles[$CountAll]/"|"*/}

DupLimitKeeper[Width,Height]=$((DupLimitKeeper[Width,Height]+1));

IfExist="${Destination}/${ImageType}${NumberOfBaseDir}/Resolution_${Width}x${Height}_DirN${SubDirNumber}"

if [ ! -d "$IfExist"  ];then 
  echo mkdir -vp "$IfExist"
NumDir=$((NumDir+1));
fi

## Creating a new numbered file type folders
if [ "${DupLimitKeeper[Width,Height]}" -gt $SDN ]; then 
  SubDirNumber=$((SubDirNumber+1));
  DupLimitKeeper[$Width,$Height]="0";
fi

## Adding a file number 
FileNameOnly="${PathToFile##*/}"
NewFileName="N${CountAll}C${FileNameOnly}"
#NewFileName="${FileNameOnly}"

## Creating a new sub-dir when limit of files in a sub-folder is reached
if [ $NumDir -gt $NBD ];then 
  NumberOfBaseDir=$((NumberOfBaseDir+1));
  NumDir="0";
fi
##
if [ -f "${PathToFile}" ];then
  echo mv -v "${PathToFile}" "$IfExist/$NewFileName";
# echo cp -v "${PathToFile}" "$IfExist/$NewFileName";
fi

CountAll=$((CountAll+1)) 
done
echo Total processed files: $CountAll