在UNIX下的我们怎么会沦落到用ruby写压缩和解压工具呢?直接上shell啊!但是请允许本猫这次可耻的用ruby来玩玩吧!其实ruby GEM中有很多压缩解压包,我选的是Zip,也许是因为名字符合KISS原则吧!不过在编写中发现Zip中的某些类没有文档中所说明的实例方法,也许在某个平台上还未实现??

话先说到前头,这个工具如果解压有重名文件的情况会直接覆盖原文件而不会有任何提示!测试时务必注意,如果造成一些文件丢失可别怪本猫啊!

代码也考虑到多文件的情况,如果是压缩多文件则默认会单独压缩每一个文件,比如:zip.rb a b c d 会产生a.zip .. d.zip四个压缩文件;但是我也考虑到现实中的情况,单独写了一个zip_n2one方法将多个文件压缩到一个文件中去,这个可以看代码实现,很清楚;如果是解压多文件则会依次解压缩每个文件,如果文件有重名会像之前说的直接覆盖。

代码未考虑到如果多个压缩文件的basename相同的情况,即zip.rb a.dat ../a.dat ~/a.dat的情况。如果真是如此,我估计压缩包中最终只有一个entry文件就是最后一个~/a.dat,要避免这种情况需要做额外的判断,我这里不是写真正的生产工具,只是个玩具嘛,所以点到为止了。

在测试代码中发现一个问题:就是如何实现删除一个目录下的所有文件,但除了zip文件。这个直接用shell吧:

apple@kissAir: tmp$ls|grep -v .*.zip|xargs -n1 rm


如果是删除所有zip文件呢?可以这样:

apple@kissAir: tmp$ls|grep .*.zip|xargs -n1 rm

不过傻了吧,为什么不直接 rm *.zip呢?
     下面上代码,写的比较快,所以有些实现略显“笨拙”,该优化的没优化,该重构的没重构!最后再提醒下:如果要多个文件打包在一个zip中请使用zip_n2one方法,注意zip_n2one方法的最终zip文件名是硬编码的,这也让人稍感不快,但这终归只是测试,所以各位童鞋可以随时重写哦:
#!/usr/bin/ruby
#简单的压缩解压工具
#code by 侯佩|hopy 2014-12-01

require 'zip/zip'

def sh_e(e)
	e.backtrace.each {|s|puts s}
	puts "ERR : #{e.to_s} \n"
end

#取得zip文件中所有的entry名称
def get_entries_name(path)
	full_path = File.expand_path(path)
	entries = []
	Zip::ZipInputStream::open(full_path) do |io|
		while (entry = io.get_next_entry)
			entries << entry.name
		end
	end
	entries
end

def unzip(path)
	full_path = File.expand_path(path)
	entries = get_entries_name(path)

	Zip::ZipFile.open(full_path) do |f|
		entries.each do |entry|
			f.extract(entry,entry) {true}
			puts "unzip #{entry} succeed!"
		end
	end
rescue =>e
	sh_e(e)
	exit 3
end

def zip_n2one(paths,zip_path)
	full_zip_path = File.expand_path(zip_path)
	f = Zip::ZipFile.open(full_zip_path,Zip::ZipFile::CREATE)
	paths.each do |path|
		full_path = File.expand_path(path)
		f.add(File.basename(path),full_path) {true}
		puts "add #{path} to #{full_zip_path}"
	end
	f.close
	puts "all files is zip to #{full_zip_path}"
rescue =>e
	sh_e(e)
	exit 4
end

def zip(path)
	full_path = File.expand_path(path)
	dir_name = File.dirname(full_path)
	only_name = File.basename(path,".*")
	only_zip_name = only_name + ".zip"
	full_zip_path = dir_name + '/' + only_zip_name

	f = Zip::ZipFile.open(full_zip_path,Zip::ZipFile::CREATE)
	f.add(File.basename(path),full_path) {true}
	f.close
	puts "create #{full_zip_path} succeed!"
rescue =>e
	sh_e(e)
	exit 5
end

is_unzip = false
case ARGV.count
	when 0
		puts "usage #{$0} [-u] files [...]"
		exit 1
	when 1
		if ARGV[0] == "-u"
			puts "ERR : unzip without filename!"
			exit 2
		end
	else
		if ARGV[0] == "-u"
			is_unzip = true
			#将选项-u从参数列表中移除
			ARGV.shift
		end
end

if is_unzip
	ARGV.each {|file_path|unzip(file_path)}
else
	#ARGV.each {|file_path|zip(file_path)}
	zip_n2one(ARGV,"total.zip")
end

ruby利用Zip Gem写一个简单的压缩和解压的小工具的更多相关文章

  1. 【阿菜做实践】利用go语言写一个简单的Pow样例

    本篇博客的主要内容是用go写一个简单的Proof-of-Work共识机制,不涉及到网络通信环节,只是一个本地的简单demo.开发IDE用的是JB Golang. 整个项目的文件结构如下: PoWdem ...

  2. GzipStream的简单使用压缩和解压

    压缩和解压都需要用到三个流实例,分别是文件读取流.文件写入流.压缩流. 读取流和写入流有多种形式,压缩流就一种GzipStream. 不同的是对于压缩,是需要用文件写入流作为创建压缩流实例的参数, 压 ...

  3. 利用SpringBoot+Logback手写一个简单的链路追踪

    目录 一.实现原理 二.代码实战 三.测试 最近线上排查问题时候,发现请求太多导致日志错综复杂,没办法把用户在一次或多次请求的日志关联在一起,所以就利用SpringBoot+Logback手写了一个简 ...

  4. 分享:计算机图形学期末作业!!利用WebGL的第三方库three.js写一个简单的网页版“我的世界小游戏”

    这几天一直在忙着期末考试,所以一直没有更新我的博客,今天刚把我的期末作业完成了,心情澎湃,所以晚上不管怎么样,我也要写一篇博客纪念一下我上课都没有听,还是通过强大的度娘完成了我的作业的经历.(当然作业 ...

  5. 利用windows.h头文件写一个简单的C语言倒计时

    今天写一个简单的倒计时函数 代码如下: #include<stdio.h> #include<windows.h> int main() { int i; printf(&qu ...

  6. 动手写一个简单版的谷歌TPU-矩阵乘法和卷积

    谷歌TPU是一个设计良好的矩阵计算加速单元,可以很好的加速神经网络的计算.本系列文章将利用公开的TPU V1相关资料,对其进行一定的简化.推测和修改,来实际编写一个简单版本的谷歌TPU.计划实现到行为 ...

  7. 动手写一个简单版的谷歌TPU-指令集

    系列目录 谷歌TPU概述和简化 基本单元-矩阵乘法阵列 基本单元-归一化和池化(待发布) TPU中的指令集 SimpleTPU实例: (计划中) 拓展 TPU的边界(规划中) 重新审视深度神经网络中的 ...

  8. 用C写一个简单的推箱子游戏(一)

    我现在在读大二,我们有一门课程叫<操作系统>,课程考查要求我们可以写一段程序或者写Windows.iOS.Mac的发展历程.后面我结合网上的资料参考,就想用自己之前简单学过的C写一关的推箱 ...

  9. 用Python写一个简单的Web框架

    一.概述 二.从demo_app开始 三.WSGI中的application 四.区分URL 五.重构 1.正则匹配URL 2.DRY 3.抽象出框架 六.参考 一.概述 在Python中,WSGI( ...

随机推荐

  1. 02_c3p0之c3p0-config.xml配置案例,操作c3p0的jdbcUtil工具类的编写

     c3p0也是一个开源jdbc连接池,我们熟悉的Hibernate和Spring框架使用的都是该数据源. 这里获得数据源使用的方法是:ComboPooledDataSource 它提供的构造方法有 ...

  2. Python图片处理库之PIL

    这个模块对于Python2.7 的windows64位电脑而言,还真的是不好找啊.这里分享一个下载链接吧,需要的朋友可以下载下来.PIL For Windows64 Python2.7下面分享一下这个 ...

  3. Mybatis3.4.0不支持mybatis-spring1.2.5及以下版本

    今天将工程的Mybatis的版本由3.3.0升级到3.4.0导致程序运行错误,使用的mybatis-spring版本是1.2.3,错误内容如下,最后发现是SpringManagedTransactio ...

  4. UNIX环境高级编程——线程限制

  5. Android官方命令深入分析之etc1tool

    etc1tool是一个命令行工具,可以将PNG图像压缩为etc1标准,并且可以进行解压缩. 用法: etc1tool infile [--help | --encode | --encodeNoHea ...

  6. TCP的流量控制与拥塞控制小结

    概述 为了提高信道的利用率TCP协议不使用停止等待协议,而是使用连续ARQ协议,意思就是可以连续发出若干个分组然后等待确认,而不是发送一个分组就停止并等待该分组的确认.其中TCP的流量控制与拥塞控制是 ...

  7. 控件的基本使用-iOS—UI笔记

    学习目标 1.[掌握]第一个UI项目 2.[掌握]控件连线 3.[掌握]按钮的基本操作 4.[掌握]控件的常用属性 一.第一个UI项目 UI (User Interface)也是就用户界面,是App的 ...

  8. OC语言实现中等难度通讯录

    实现中等难度通讯录.需求: 1.定义联系⼈人类Contact.实例变量:姓名(拼⾳音,⾸首字⺟母⼤大写).性别.电话号码. 住址.分组名称.年龄.⽅方法:⾃自定义初始化⽅方法(姓名.电话号码).显⽰示 ...

  9. java的hashmap与hashtable说明,简单易理解

    1. HashMap 1) hashmap的数据结构 Hashmap是一个数组和链表的结合体(在数据结构称"链表散列"),如下图示: 当我们往hashmap中put元素的时候,先根 ...

  10. Android学习之旅-android系统服务的启动过程以及分类(90)

    读了android开发精要这本书,所以我把书中的比较精彩的地方截图了,一块分享一下