Automator/Apple 脚本:将具有相同前缀的文件移动到新文件夹中。文件夹名称必须是文件前缀

Automator/Apple Script: Move files with same prefix on a new folder. The folder name must be the files prefix

我是一名摄影师,我在一个文件夹中有多个 jpg 服装文件。文件名结构为:

TYPE_FABRIC_COLOR(示例:BU23W02CA_CNU_RED、BU23W02CA_CNU_BLUE、BU23W23MG_LINO_WHITE)

我必须将相同类型 (BU23W02CA) 的文件移动到一个名为 TYPE 的文件夹中。

例如:

MAIN FOLDER>

BU23W02CA_CNU_RED.jpg, BU23W02CA_CNU_BLUE.jpg, BU23W23MG_LINO_WHITE.jpg

变成:

MAIN FOLDER>

BU23W02CA_CNU > BU23W02CA_CNU_RED.jpg, BU23W02CA_CNU_BLUE.jpg

BU23W23MG_LINO > BU23W23MG_LINO_WHITE.jpg

这是一些脚本。

V1

#!/bin/bash

find . -maxdepth 1 -type f -name "*.jpg" -print0 | while IFS= read -r -d '' file
do
    # Extract the directory name
    dirname=$(echo "$file" | cut -d'_' -f1-2 | sed 's#\./\(.*\)##')
    #DEBUG echo "$file --> $dirname"

    # Create it if not already existing
    if [[ ! -d "$dirname" ]]
    then
        mkdir "$dirname"
    fi

    # Move the file into it
    mv "$file" "$dirname"
done
  • 它假定 find 列表中的所有文件都具有您在问题中描述的格式,即 TYPE_FABRIC_COLOR.ext
  • dirname是提取文件名中_分隔的前两个单词。
  • 由于 find 列出了带有 ./ 前缀的文件,它也从 dirname 中删除(这就是 sed 命令的作用)。
  • find 指定要考虑的文件名 *.jpg。如果您想限制在移动中考虑哪些文件,您可以将其更改为其他内容。
  • 此版本遍历每个文件,创建一个包含前两部分的目录(如果它不存在),然后将文件移入其中。
  • 如果您想查看脚本对每个文件执行的操作,可以将选项 -v 添加到 mv 命令。我用它来调试。

但是,由于它逐个循环遍历每个文件,因此对于大量文件这可能需要时间,因此是下一个版本。


V2

#!/bin/bash

while IFS= read -r dirname
do
    echo ">$dirname"

    # Create it if not already existing
    if [[ ! -d "$dirname" ]]
    then
        mkdir "$dirname"
    fi

    # Move the file into it
    find . -maxdepth 1 -type f -name "${dirname}_*" -exec mv {} "$dirname" \;
done < <(find . -maxdepth 1 -type f -name "*.jpg" -print | sed 's#^\./\(.*\)_\(.*\)_.*\..*$#_#' | sort | uniq)
  • 此版本在目录名称而不是每个文件上循环。
  • 最后一行做了“魔术”。它 find 所有文件,并立即提取前两个单词(sed)。然后这些词被 sorted 和 "uniqued".
  • while 循环然后一个一个地创建每个目录。
  • while 循环中的 find 将所有与正在处理的目录匹配的文件移动到其中。为什么我不简单地做 mv ${dirname}_* ${dirname}?由于 * 通配符的扩展可能导致 mv 命令的参数列表过长。使用 find 确保它即使在大量文件上也能工作。

建议单行awk脚本:

echo "$(ls -1 *.jpg)"| awk '{system("mkdir -p " OFS );system("mv "[=10=]" " OFS )}' FS=_ OFS=_

解释:

echo "$(ls -1 *.jpg)": 列出当前目录下的所有jpg文件,每行一个文件

FS=_ :将awk字段分隔符设置为_ $1=type $2=fabric $3=color.jpg

OFS=_ :设置awk输出字段分隔符为_

awk脚本解释

{ # for each file name from list
  system ("mkdir -p " OFS ); # execute "mkdir -p type_fabric"
  system ("mv " [=11=] " "  OFS ); # execute "mv current-file to type_fabric"
}