[英]How to rename files in zip archive without extracting and recompressing them?
I need to rename all the files on a zip file from AAAAA-filename.txt
to 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.我需要将 zip 文件中的所有文件从
AAAAA-filename.txt
重命名为BBBBB-filename.txt
,我想知道是否可以自动执行此任务而无需提取所有文件、重命名然后再次压缩。 Unzipping one at a time, renaming and zipping again is acceptable.一次解压缩一个,重命名并再次压缩是可以接受的。
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.但我不知道是否有更高级的版本,我不必使用所有额外的磁盘空间。
plan计划
- find offsets of filenames with strings
用字符串查找文件名的偏移量
- use dd to overwrite new names ( note will only work with same filename lengths ).
使用 dd 覆盖新名称(注意仅适用于相同的文件名长度)。 otherwise would also have to find and overwrite the filenamelength field..
否则还必须找到并覆盖文件名长度字段..
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\).*$/\1 \2\3 BBBBB\3/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
We used python to我们使用 python 来
xyz.zip
file to xyz_renamed/
folderxyz.zip
文件解压到xyz_renamed/
文件夹renameFile
function (we are changing names to lower)renameFile
函数中重命名所需的文件(我们只重命名 jpeg 和 png 图像)(我们将名称更改为更低)xyz_renamed.zip
xyz_renamed.zip
xyz_renamed/
folder and xyz.zip
filexyz_renamed/
文件夹和xyz.zip
文件xyz_renamed.zip
to xyz.zip
xyz_renamed.zip
重命名为xyz.zip
import os
from zipfile import ZipFile
import shutil
# rename the individual file and return the absolute path of the renamed file
def renameFile(root, fileName):
toks = fileName.split('.')
newName = toks[0].lower()+'.'+toks[1]
renamedPath = os.path.join(root,newName)
os.rename(os.path.join(root,fileName),renamedPath)
return renamedPath
def renameFilesInZip(filename):
# Create <filename_without_extension>_renamed folder to extract contents into
head, tail = os.path.split(filename)
newFolder = tail.split('.')[0]
newFolder += '_renamed'
newpath = os.path.join(head, newFolder)
if(not os.path.exists(newpath)):
os.mkdir(newpath)
# extracting contents into newly created folder
print("Extracting files\n")
try:
with ZipFile(filename, 'r', allowZip64=True) as zip_ref:
zip_ref.extractall(newpath)
zip_ref.close()
except ResponseError as err:
print(err)
return -1
# track the files that need to be repackaged in the zip with renamed files
filesToPackage = []
for r, d, f in os.walk(newpath):
for item in f:
# filter the file types that need to be renamed
if item.lower().endswith(('.jpg', '.png')):
# renaming file
renamedPath = renameFile(r, item)
filesToPackage.append(renamedPath)
else:
filesToPackage.append(os.path.join(r,item))
# creating new zip file
print("Writing renamed file\n")
zipObj = ZipFile(os.path.join(head, newFolder)+'.zip', 'w', allowZip64 = True)
for file in filesToPackage:
zipObj.write(file, os.path.relpath(file, newpath))
zipObj.close()
# removing extracted contents and origianl zip file
print('Cleaning up \n')
shutil.rmtree(newpath)
os.remove(filename)
# renaming zipfile with renamed contents to original zipfile name
os.rename(os.path.join(head, newFolder)+'.zip', filename)
Use the following code to invoke the renaming function for multiple zip files使用以下代码调用多个zip文件的重命名功能
if __name__ == '__main__':
# zipfiles with contents to be renamed
zipFiles = ['/usr/app/data/mydata.zip', '/usr/app/data/mydata2.zip']
# do the renaming for all files one by one
for _zip in zipFiles:
renameFilesInZip(_zip)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.