Bash - 存档名称到文件名,不正确的匹配(zip、cdg、mp3)

Bash - 存档名称到文件名,不正确的匹配(zip、cdg、mp3)

我编写了一个脚本来检查 zip 存档中的两个特定扩展名。进行一些检查以确定存档是否只有 2 个文件,然后对其进行处理。如果存档少于 2 个,则会将存档移动到“BAD”文件夹。如果存档超过 2 个,它会将存档移动到“FIX”目录。

该过程步骤是提取文件,并将它们重命名为与 zip 存档相同的名称。

当条件完美时,一切都会顺利进行。但当条件不完美时……情况就会变得糟糕。

我遇到的情况是,即使文件可能具有正确的 2 个文件和扩展名,但如果文件具有特殊字符(例如 Ø、反引号、逗号、撇号等)...它们会被处理(我假设)像正则表达式语法或表达式。

这是代码:

#! /bin/bash

prefix="0000_"

mkdir -p ${prefix}{DONE,FIX,BAD}

shopt -s nocaseglob
for i in *.ZIP;
    do
        zip_name="$i"
        pair_exists=$(unzip -Z1 "$i" | grep -E -- '.cdg|.CDG|.mp3|.MP3' | wc -l)
        log="${prefix}LOG.txt"

        if [ $pair_exists -eq 2 ]
            then
                cdg_name=$(unzip -Z1 "$i" | grep -E -- '.cdg|.CDG' | awk '{print substr($0,index($0,$1))}')
                mp3_name=$(unzip -Z1 "$i" | grep -E -- '.mp3|.MP3' | awk '{print substr($0,index($0,$1))}')
                new_cdg_name="$(echo "${zip_name%.*}.cdg")"
                new_mp3_name="$(echo "${zip_name%.*}.mp3")"
                7za x "$i" -aoa -y -ba >> ./$log
                mv ./"$cdg_name" ./"$new_cdg_name"
                mv ./"$mp3_name" ./"$new_mp3_name"
                mv ./"$zip_name" ./${prefix}DONE/

        elif [ $pair_exists -gt 2 ]
            then
                echo ""
                echo "NEEDS FIXED: $zip_name"
                mv ./"$zip_name" ./${prefix}FIX/

        elif [ $pair_exists -lt 2 ]
            then
                echo ""
                echo "ARCHIVE IS BAD: $zip_name"
                mv ./"$zip_name" ./${prefix}BAD/

        else
                echo ""
                echo "MUST BE BROKE!"
                echo ""
        fi
    done
exit

一切都很酷,直到我看到MV声明。

                mv ./"$cdg_name" ./"$new_cdg_name"
                mv ./"$mp3_name" ./"$new_mp3_name"

我觉得也许 mv 可能不是这里使用的正确方法,但我在重命名方面也遇到了严重的问题。我想更多的是,我需要一些代码来告诉命令不要将变量中的任何字符视为要执行的操作。

这是我所看到的情况......

----- 示例 1 -----

压缩文件名:

     CB30035-05 - 简单计划 - 我愿意做任何事情.zip

Zip 内的文件:

     CB30035-05 - 简单计划 - 我愿意做任何事.cdg
     CB30035-05 - 简单的计划 - 我愿意做任何事情.mp3

错误:

     mv: 无法 stat './CB30035-05 - Simple PlanI\'d Do Anything.cdg': 没有这样的文件或目录
     mv: 无法 stat './CB30035-05 - Simple PlanI\'d Do Anything.mp3': 没有这样的文件或目录

----- 示例 2 -----

压缩文件名:

     CBSE5-0068 - 木匠,我们所知道的.zip

Zip 内的文件:

     cbscdge450-5-0068 - 木匠 - 我们所知道的.cdg
     cbscdge450-5-0068 - 木匠 - 我们所知道的.mp3

错误:
mv: 无法 stat './cbscdge450-5-0068 - Carpenters - For All We Know.cdg\ncbscdge450-5-0068 - Carpenters - For All We Know.mp3': 没有这样的文件或目录

我已经搜索过类似的问题,但我发现的主题并不真正适合我的问题,或者某些代码有点超出我的头脑,无法尝试弄清楚如何合并到我的脚本中。

我将不胜感激任何帮助。谢谢你!

(注意:我知道上面脚本中的“awk”没有执行任何操作。我转到“unzip -Z1”,这似乎解决了我之前从 zip 文件中获取文件名的努力。我已经离开把它放进去并调整它只是为了保留它以备不时之需。)



编辑2020120601:


为了回应@Wieland,我从 zip 文件名中删除了双空格。但在里面的文件上留下了双倍的空间。我无法修复每个文件的内部,因为有很多文件,所以我需要弄清楚如何按原样修复它们。删除 zip 文件上的双空格并没有改变我的结果。

为了回应@steeldriver,这里有更多信息。下面是我尝试使用的每个命令的返回结果(注意 7za...它没有办法只生成文件名,所以我之前使用的是 awk)。

我还更改了要读取的代码\.cdg$|\.CDG$|\.mp3$|\.MP3$,这并没有改变我的结果,但我同意将覆盖该基础。

zipinfo -1“CB30035-05 - 简单计划 - 我愿意做任何事情.zip”

  CB30035-05 - 简单计划我会做任何事.cdg
  CB30035-05 - 简单的计划我会做任何事情.mp3

unzip -Z1“CB30035-05 - 简单计划 - 我愿意做任何事情.zip”

  CB30035-05 - 简单计划我会做任何事.cdg
  CB30035-05 - 简单的计划我会做任何事情.mp3

7za -ba l“CB30035-05 - 简单计划 - 我愿意做任何事情.zip”           

   2003-06-27 14:41:56 ....A 1516512 379652 CB30035-05 - 简单计划我会做任何事.cdg
   2003-06-27 14:42:22 ....A 3369876 3112004 CB30035-05 - 简单计划我会做任何事情.mp3



编辑2020120701:


@G-Man 说“恢复莫妮卡”

感谢您在解释中包含了如此多的细节。我很感激。我会将您建议的模组合并到脚本中。关于

如果您“将代码更改为读取 .cdg$|.CDG$|.mp3$|.MP3$ 并且这并没有改变我的结果”,那么您就做错了......

我很确定我严格遵循了你的例子。我曾评论说我这样做了,但反斜杠被从我的评论中删除了。我也已经实现了 grep "c"。但显然严重错过了“i”选项。这肯定会清理掉它。

这是现在的代码......

#! /bin/bash

prefix="00001_"

mkdir -p ${prefix}{DONE,FIX,BAD}

shopt -s nocaseglob
for i in *.ZIP;
    do
        zip_name="$i"
        pair_exists=$(unzip -Z1 "$i" | grep -Eci -- '\.cdg$|\.mp3$')

        if [ $pair_exists -eq 2 ]
            then
                cdg_name=$(unzip -Z1 "$i" | grep -E -- '\.cdg$|\.CDG$')
                mp3_name=$(unzip -Z1 "$i" | grep -E -- '\.mp3$|\.MP3$')

                base_name="${zip_name%.*}"
                new_cdg_name="$base_name.cdg"
                new_mp3_name="$base_name.mp3"

                        printf 'cdg_name = [%s]\n' "$cdg_name"
                        printf 'mp3_name = [%s]\n' "$mp3_name"

                unzip -qq "$i"
                mv -- "${cdg_name}" "${new_cdg_name}"
                mv -- "${mp3_name}" "${new_mp3_name}"
                mv ./"$zip_name" ./${prefix}DONE/

        elif [ $pair_exists -gt 2 ]
            then
                echo ""
                echo "NEEDS FIXED: $zip_name"
                mv ./"$zip_name" ./${prefix}FIX/

        elif [ $pair_exists -lt 2 ]
            then
                echo ""
                echo "ARCHIVE IS BAD: $zip_name"
                mv ./"$zip_name" ./${prefix}BAD/

        else
                echo ""
                echo "HMM"
                echo ""
        fi
    done
exit

我也合并了您的更改。

关于调试,我再次使用了“echo”。这就是我的测试脚本中的内容......

echo ""
echo "-----"
echo   $pair_exists
echo   $zip_name
echo   $cdg_name
echo   $mp3_name
echo   $new_cdg_name
echo   $new_mp3_name
echo   $prefix
echo   $log
echo "-----"
echo ""

它产生与你的“printf”相同的东西。不过我很喜欢你的奇特风格,并且会采用你的风格。 :)

回答第 5 点。我通过使用 7z.exe 得到了这个想法。实际上是通过 GUI 来查看的。现在我将发布我的 Windows 机器所看到的屏幕截图,然后我将再次发布我的 linux 机器所产生的内容。

视窗:

在此输入图像描述

操作系统:

在此输入图像描述

我不知道为什么会发生这种情况。看了一会儿之后,我的一部分认为也许......我不知何故搞砸了我的环境。我以前从未遇到过这样的问题,这让我抓狂!

现在! 给你所有这些信息之后,也许我给你的还不够。但我需要告诉你。对代码进行更改后,它会产生正确的结果!尽管我的系统仍然从文件名中删除“-”,但它正在产生所需的最终结果。我希望这些文件采用 zip 文件的名称,这就是它现在正在做的事情。

在此输入图像描述

我所做的改变...

  1. 清理了pair_exists
    unzip -Z1 "$i" | grep -Eci -- '\.cdg$|\.mp3$'

  2. 清理 cdg 和 mp3_name 提取并删除 awk
    cdg_name=$(unzip -Z1 "$i" | grep -E -- '\.cdg$|\.CDG$')
    mp3_name=$(unzip -Z1 "$i" | grep -E -- '\.mp3$|\.MP3$')

  3. 合并了新的 base_name 建议并删除了 echo
    base_name="${zip_name%.*}"
    new_cdg_name="$base_name.cdg"
    new_mp3_name="$base_name.mp3"

  4. 添加了“printf”调试行(在执行 150k+ 文件时将注释掉它们)
    printf 'cdg_name = [%s]\n' "$cdg_name"
    printf 'mp3_name = [%s]\n' "$mp3_name"

  5. 我将解压缩器更改为 unzip 以与工具集保持一致
    unzip -qq "$i"

我不知道修复发生在哪里,但我真的很感谢你的帮助@G-Man 说“恢复莫妮卡”并帮助我解决这个问题并提供了一些非常可靠的建议。

谢谢你!


答案1

  1. 钢铁司机的评论几乎可以肯定地找出了部分问题。如果你“改变了读取的代码\.cdg$|\.CDG$|\.mp3$|\.MP3$ ,但这并没有改变我的结果”,那么你就做错了——具体来说,你做得不完整。部分问题出在命令上

    cdg_name=$(unzip -Z1 "$i" | grep -E -- '.cdg|.CDG' | awk '{print substr($0,index($0,$1))}')
    

    必须改为

    cdg_name=$(unzip -Z1 "$i" | grep -E -- '\.cdg$|\.CDG$' | awk '{print substr($0,index($0,$1))}')
    

    因为 匹配,所以设置为cbscdge450-5-0068 - Carpenters ….cdgcdg_name的串联两个名字,用换行符分隔。  从错误消息中可以清楚地看出这一点mv

  2. 只是为了简化目的,您可以更改

    unzip -Z1 "$i" | grep -E -- '\.cdg$|\.CDG$|\.mp3$|\.MP3$' | wc -l
    

    unzip -Z1 "$i" | grep -Ec -- '\.cdg$|\.CDG$|\.mp3$|\.MP3$'
    

    (使用C的计数选项grep) 甚至

    unzip -Z1 "$i" | grep -Eci -- '\.cdg$|\.mp3$'
    

    (使用忽略 )的大小写选项grep

  3. 几乎没有任何理由说。事实上,我倾向于说从来没有理由这样做,但有人可能会发现一个奇怪的极端情况,在这种情况下这样做是有益的。具体来说,$(echo "something")

    new_cdg_name="$(echo "${zip_name%.*}.cdg")"
    new_mp3_name="$(echo "${zip_name%.*}.mp3")"
    

    可以改为

    new_cdg_name="${zip_name%.*}.cdg"
    new_mp3_name="${zip_name%.*}.mp3"
    

    我什至可能会把它们改成

    base_name="${zip_name%.*}"
    new_cdg_name="$base_name.cdg"
    new_mp3_name="$base_name.mp3"
    

    PS 严格来说,上面的引号不是必需的,但最好始终使用它们,除非您有充分的理由不这样做。
    PPS 在错误的上下文中,可以执行诸如更改为 (即,将多个空格压缩为一个)之 类的操作。$(echo "something")Plan  - IPlan - I

  4. 冒着政治不正确的风险,想象一下你是试图破案的警察,而你所能做的就是拿着双筒望远镜坐在犯罪分子总部外面。如果你能得到窃听器或线人,这样你就可以知道大楼内发生了什么,不是更好吗?调试就像试图解决犯罪问题——虽然外部信息(即,zipinfo和的输出7za,单独运行)对于理解问题很重要,但它确实有助于获取内部信息。因此,作为例行调试步骤,我建议添加如下语句

    printf 'cdg_name = [%s]\n' "$cdg_name"
    printf 'mp3_name = [%s]\n' "$mp3_name"
    

    到脚本。这会很明显地cdg_name设置为两个名称的串联,并且它可能会帮助您I'd Do Anything跟踪I\'d Do Anything.

  5. 严格来说,这应该是一条评论,但是,只要我在这里:您从哪里得知其中的成员文件的名称CB30035-05 - SIMPLE PLAN - I'D DO ANYTHING.zip

    • CB30035-05 - Simple Plan - I'd Do Anything.cdg
    • CB30035-05 - Simple Plan - I'd Do Anything.mp3

    当你没有向我们展示任何显示的命令时任何事物 和 Plan之间 I

  6. 正如我上面提到的,这I\'d Do Anything是一个谜题。但是您是否真的有与逗号、反引号或非 ASCII 字符(如“é”、“Φ”、“Ø”、“θ”、“½”或“∞”)相关的问题示例?

相关内容