bash 如何在不解压缩和重新压缩它们的情况下重命名 zip 存档中的文件?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/32829839/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-18 13:39:14  来源:igfitidea点击:

How to rename files in zip archive without extracting and recompressing them?

linuxbash

提问by Topo

I need to rename all the files on a zip file from AAAAA-filename.txtto BBBBB-filename.txt, and I want to know if I can automate this task without having to extract all files, rename and then zip again. Unzipping one at a time, renaming and zipping again is acceptable.

我需要在所有的压缩文件中的文件从命名AAAAA-filename.txtBBBBB-filename.txt了,我想知道如果我可以,而不必提取所有文件,重命名自动执行此任务,然后再压缩。一次解压缩一个,重命名并再次压缩是可以接受的。

What I have now is:

我现在拥有的是:

for file in *.zip
do
    unzip $file
    rename_txt_files.sh
    zip *.txt $file
done;

But I don't know if there is a fancier version of this where I don't have to use all that extra disk space.

但我不知道是否有更高级的版本,我不必使用所有额外的磁盘空间。

回答by amdixon

plan

计划

  • find offsets of filenames with strings
  • use dd to overwrite new names ( note will only work with same filename lengths ). otherwise would also have to find and overwrite the filenamelength field..
  • 用字符串查找文件名的偏移量
  • 使用 dd 覆盖新名称(注意仅适用于相同的文件名长度)。否则还必须找到并覆盖文件名长度字段..

backup your zipfile before trying this

在尝试之前备份您的 zipfile

zip_rename.sh

zip_rename.sh

#!/bin/bash

strings -t d test.zip | \
grep '^\s\+[[:digit:]]\+\sAAAAA-\w\+\.txt' | \
sed 's/^\s\+\([[:digit:]]\+\)\s\(AAAAA\)\(-\w\+\.txt\).*$/  BBBBB/g' | \
while read -a line; do
  line_nbr=${line[0]};
  fname=${line[1]};
  new_name=${line[2]};
  len=${#fname};
#  printf "line: "$line_nbr"\nfile: "$fname"\nnew_name: "$new_name"\nlen: "$len"\n";
  dd if=<(printf $new_name"\n") of=test.zip bs=1 seek=$line_nbr count=$len conv=notrunc  
done;

output

输出

$ ls
AAAAA-apple.txt  AAAAA-orange.txt  zip_rename.sh
$ zip test.zip AAAAA-apple.txt AAAAA-orange.txt 
  adding: AAAAA-apple.txt (stored 0%)
  adding: AAAAA-orange.txt (stored 0%)
$ ls
AAAAA-apple.txt  AAAAA-orange.txt  test.zip  zip_rename.sh
$ ./zip_rename.sh 
15+0 records in
15+0 records out
15 bytes (15 B) copied, 0.000107971 s, 139 kB/s
16+0 records in
16+0 records out
16 bytes (16 B) copied, 0.000109581 s, 146 kB/s
15+0 records in
15+0 records out
15 bytes (15 B) copied, 0.000150529 s, 99.6 kB/s
16+0 records in
16+0 records out
16 bytes (16 B) copied, 0.000101685 s, 157 kB/s
$ unzip test.zip 
Archive:  test.zip
 extracting: BBBBB-apple.txt         
 extracting: BBBBB-orange.txt        
$ ls
AAAAA-apple.txt   BBBBB-apple.txt   test.zip
AAAAA-orange.txt  BBBBB-orange.txt  zip_rename.sh
$ diff -qs AAAAA-apple.txt BBBBB-apple.txt 
Files AAAAA-apple.txt and BBBBB-apple.txt are identical
$ diff -qs AAAAA-orange.txt BBBBB-orange.txt 
Files AAAAA-orange.txt and BBBBB-orange.txt are identical