如何重命名/提取 zip 档案中名称较长的文件

如何重命名/提取 zip 档案中名称较长的文件

我有一个 zip 文件,其中包含名称很长的文件。

如果我尝试在命令行上提取文件,则会收到错误“文件名太长”。
如果我使用图形存档管理器,它不会提取文件,也不会让我重命名它们。如果我挂载存档,也会出现同样的问题。

我可以使用以下方法单独提取和重命名文件:

unzip -p -c example.zip "long file name.ogg" > shortname.ogg

对于大量文件来说这是不切实际的。

是否有一个工具可以在提取文件名时截断它们?

答案1

提取

我们可以将其用作zipinfo这个过程的一部分,它是一个来自zip包的程序。

zipinfo -2 example.zip

将只显示文件名称example.zip,如下所示:

file1-long-name-...-bla-bla.html
file2-long-name-...-bla-bla.html

因此我们可以利用这个特性来提取所有文件:

zipinfo -2 example.zip | while read i;
do
  long_fname=${i%.*}
  unzip -p -c example.zip "$i" > "${long_fname:0:250}.${i##*.}"
done;
  • long_fname=${i%.*}:从长文件名中删除扩展名,因此如果文件名少于 256 个字符,我们就不会得到重复的扩展名。
  • ${long_fname:0:250}.${i##*.}:创建一个具有合法字符数的新文件名,并添加.文件真实扩展名。

简单地说,我们循环进入文件列表,并使用 256 个字符的新合法文件名提取每个文件。


重命名

您可以使用zipnote命令,它也是包的一部分zip

首先备份你的 zip 文件。

运行此命令:

zipnote example.zip > names

使用编辑器打开名称,它看起来像这样:

@ file name long in zip and a lot of other strings in the file name
@ (comment above this line)
@ (zip file comment below this line)

添加新的文件名,如下所示:

@ file name long in zip and a lot of other strings in the file name
@=new short name for above file
@ (comment above this line)
@ (zip file comment below this line)

然后重命名文件使用:

zipnote -w example.zip < names

您可以将它们全部重命名,也可以编写一个简单的脚本来自动为您执行此操作。

答案2

即使将输出文件名长度减少到 100,出于某种原因,另一个答案对我来说也不起作用,因此我只是一次性提取所有文件,unzip -p > all.txt然后根据某种模式拆分all.txt文件。csplit

请注意,解压缩将添加如下行

------=_Part_4952_1005066427.1638023175221

    boundary="----=_Part_4953_1221949914.1638023175221"

它应该从输出中删除,并可能用于拆分文件,但我不需要这样做,因此如何正确地做到这一点留给练习:)

答案3

这是也可以处理长目录名的版本。您可以将其作为函数添加到 ~/.bashrc 或存储函数或别名的任何位置。

unziplong() {
    max_base_len=100
    max_ext_len=15
    zipinfo -1 "$1" | grep -v "/$" | while read orig_path
    do
        new_path=""
        current_path="$orig_path"
        while [[ "$current_path" != "." ]]
        do
            segment="$(basename -- "$current_path")"
            ext="$([[ "$segment" =~ .*\..{1,$max_ext_len}$ ]] && echo ".${segment##*.}" || echo)"
            base="${segment%$ext}"
            segment="/$(xargs <<< "${base:0:$max_base_len}")$(xargs <<< "$ext")"
            new_path="$segment$new_path"
            current_path="$(dirname -- "$current_path")"
        done
        new_path="${new_path:1}"
        new_dir="$(dirname -- "$new_path")"
        mkdir -p "$new_dir"
        unzip -p "$1" "$orig_path" > "$new_path"
    done
}

相关内容