根据第四个下划线之前的文件名创建目录

Make directory based on filenames before fourth underscore

我有这些测试文件:

ABCD1234__12_Ab2_Hh_3P.mp4
ABCD1234__12_Ab2_Lw_3P.wmv
ABCD1234__12_Ab2_SSV.mov
EFGH56789__13_Mn1_SSV.avi
EFGH56789__13_Mn1_Ve1_3P.mp4
EFGH56789__13_Mn1_Ve2_3P.webm

我想在 Automator 中创建一个上下文服务,它根据上面的文件名前缀创建目录,如下所示:

ABCD1234__12_Ab2
EFGH56789__13_Mn1

...并将文件相应地移动到这两个文件中。名称中唯一一致的变量是下划线,所以我想我可以通过这些来描述,最好在第四个之前捕获名称。

我最初是从这个非常简单的脚本开始的:

for file in "$@"
do
mkdir "${file%.*}" && mv "$file" "${file%.*}"
done

这会为每个文件创建一个文件夹,并将每个文件移动到它自己的文件夹中。

我尝试添加变量、各种 if/thens 等,但无济于事(不是程序员的职业)。

我还写了另一个脚本来以稍微不同的方式完成它,但结果相同:

for folder in "$@"
do
cd ""
find . -type f -maxdepth 1 -exec bash -c 'mkdir -p "${0%.*}"' {} \; \
-exec bash -c 'mv "[=13=]" "${0%.*}"' {} \;
done

我觉得我明显遗漏了什么。

你可以这样做:

#!/bin/bash
shopt -s extglob

for file
do
    if [[ $file =~ ^(([^_]*_){3}[^_]*) ]]
    then
        echo "${BASH_REMATCH[0]}"
    else
        echo "${file%.*}"
    fi
done

你的脚本是按点分割的,但你说你想按下划线分割。如果您要拆分的是最后一个,则修复很简单:

for file in "$@"
do
    mkdir -p "${file%_*}" && mv "$file" "${file%_*}"
done

要准确地获得第四个,请尝试

for file in "$@"
do
    tail=${file#*_*_*_*_}
    dir=${file%_"$tail"}
    mkdir -p "$dir" && mv "$file" "$dir"
done

如果您想在此处使用&&,则添加-p选项是必要的错误修复; mkdir 如果目录已经存在,没有这个选项将会失败。

也许另请参阅 the section about parameter expansions in the Bash Reference Manual,其中解释了此语法及其变体。