Gore Liu 6 years ago
parent
commit
e91c653677

+ 2 - 0
00_Zsh-开发指南(目录).md

@@ -272,7 +272,9 @@
 ### [实例四:根据文件的 md5 删除重复文件](19_Zsh-开发指南(第十九篇-脚本实例讲解).md#实例四根据文件的-md5-删除重复文件)
 ### [实例五:转换 100 以内的汉字数字为阿拉伯数字](19_Zsh-开发指南(第十九篇-脚本实例讲解).md#实例五转换-100-以内的汉字数字为阿拉伯数字)
 ### [实例六:为带中文汉字数字的文件名重命名成以对应数字开头](19_Zsh-开发指南(第十九篇-脚本实例讲解).md#实例六为带中文汉字数字的文件名重命名成以对应数字开头)
+### [实例七:统一压缩解压工具](19_Zsh-开发指南(第十九篇-脚本实例讲解).md#实例七统一压缩解压工具)
 ### [总结](19_Zsh-开发指南(第十九篇-脚本实例讲解).md#总结)
+### [更新历史](19_Zsh-开发指南(第十九篇-脚本实例讲解).md#更新历史)
 
 ---
 

+ 343 - 0
19_Zsh-开发指南(第十九篇-脚本实例讲解).md

@@ -366,6 +366,349 @@ for i (Zsh*.md) {
 }
 ```
 
+### 实例七:统一压缩解压工具
+
+功能:Linux 下常用的压缩、归档格式众多,参数各异,写一个用法统一的压缩解压工具,用于创建、解压 `.zip` `.7z` `.tar` `.tgz` `.tbz2` `.txz` `.tar.gz` `.tar.bz2` `.tar.xz` `.cpio` `.ar` `.gz` `.bz2` `.xz` 等文件。
+
+例子:
+
+```
+# a 用于创建压缩文件
+% a a.tgz dir1 file1 file2
+dir1/
+file1
+file2
+
+# al 用于列出压缩文件中的文件列表
+% al a.tgz
+drwxr-xr-x goreliu/goreliu   0 2017-09-13 11:23 dir1/
+-rw-r--r-- goreliu/goreliu   3 2017-09-13 11:23 file1
+-rw-r--r-- goreliu/goreliu   3 2017-09-13 11:23 file2
+
+# x 用于解压文件
+% x a.tgz
+dir1/
+file1
+file2
+a.tgz  ->  a
+
+# 如果解压后的文件名或目录名中当前目录下已经存在,则解压到随机目录
+% x a.tgz
+dir1/
+file1
+file2
+a.tgz  ->  /tmp/test/x-c4I
+```
+
+思路:
+
+1. 压缩文件时,根据传入的文件名判断压缩文件的格式。
+2. 解压和查看压缩文件内容时,根据传入的文件名和 `file` 命令结果判断压缩文件的格式。
+3. 为了复用代码,多个命令整合到一个文件,然后 `ln -s` 成多个命令。
+
+实现:
+
+```
+#!/bin/zsh
+
+get_type_by_name() {
+    case $1 {
+        (*.zip|*.7z|*.jar)
+        echo 7z
+        ;;
+
+        (*.rar|*.iso)
+        echo 7z_r
+        ;;
+
+        (*.tar|*.tgz|*.txz|*.tbz2|*.tar.*)
+        echo tar
+        ;;
+
+        (*.cpio)
+        echo cpio
+        ;;
+
+        (*.cpio.*)
+        echo cpio_r
+        ;;
+
+        (*.gz)
+        echo gz
+        ;;
+
+        (*.xz)
+        echo xz
+        ;;
+
+        (*.bz2)
+        echo bz2
+        ;;
+
+        (*.lzma)
+        echo lzma
+        ;;
+
+        (*.lz4)
+        echo lz4
+        ;;
+
+        (*.ar)
+        echo ar
+        ;;
+
+        (*)
+        return 1
+        ;;
+    }
+}
+
+get_type_by_file() {
+    case $(file -bz $1) {
+        (Zip *|7-zip *)
+        echo 7z
+        ;;
+
+        (RAR *)
+        echo 7z_r
+        ;;
+
+        (POSIX tar *|tar archive)
+        echo tar
+        ;;
+
+        (*cpio archive*)
+        echo cpio
+        ;;
+
+        (*gzip *)
+        echo gz
+        ;;
+
+        (*XZ *)
+        echo xz
+        ;;
+
+        (*bzip2 *)
+        echo bz2
+        ;;
+
+        (*LZMA *)
+        echo lzma
+        ;;
+
+        (*LZ4 *)
+        echo lz4
+        ;;
+
+        (current ar archive)
+        echo ar
+        ;;
+
+        (*)
+        return 1
+        ;;
+    }
+}
+
+
+(($+commands[tar])) || alias tar=bsdtar
+(($+commands[cpio])) || alias cpio=bsdcpio
+
+case ${0:t} {
+    (a)
+
+    (($#* >= 2)) || {
+        echo Usage: $0 target files/dirs
+        return 1
+    }
+
+    case $(get_type_by_name $1) {
+        (7z)
+        7z a $1 $*[2,-1]
+        ;;
+
+        (tar)
+        tar -cavf $1 $*[2,-1]
+        ;;
+
+        (cpio)
+        find $*[2,-1] -print0 | cpio -H newc -0ov > $1
+        ;;
+
+        (gz)
+        gzip -cv $*[2,-1] > $1
+        ;;
+
+        (xz)
+        xz -cv $*[2,-1] > $1
+        ;;
+
+        (bz2)
+        bzip2 -cv $*[2,-1] > $1
+        ;;
+
+        (lzma)
+        lzma -cv $*[2,-1] > $1
+        ;;
+
+        (lz4)
+        lz4 -cv $2 > $1
+        ;;
+
+        (ar)
+        ar rv $1 $*[2,-1]
+        ;;
+
+        (*)
+        echo $1: error
+        return 1
+        ;;
+    }
+    ;;
+
+    (al)
+
+    (($#* >= 1)) || {
+        echo Usage: $0 files
+        return 1
+    }
+
+    for i ($*) {
+        case $(get_type_by_name $i || get_type_by_file $i) {
+            (7z|7z_r)
+            7z l $i
+            ;;
+
+            (tar)
+            tar -tavf $i
+            ;;
+
+            (cpio|cpio_r)
+            cpio -itv < $i
+            ;;
+
+            (gz)
+            zcat $i
+            ;;
+
+            (xz)
+            xzcat $i
+            ;;
+
+            (bz2)
+            bzcat $i
+            ;;
+
+            (lzma)
+            lzcat $i
+            ;;
+
+            (lz4)
+            lz4cat $i
+            ;;
+
+            (ar)
+            ar tv $i
+            ;;
+
+            (*)
+            echo $i: error
+            ;;
+        }
+    }
+    ;;
+
+    (x)
+
+    (($#* >= 1)) || {
+        echo Usage: $0 files
+        return 1
+    }
+
+    for i ($*) {
+        local outdir=${i%.*}
+
+        [[ $outdir == *.tar ]] && {
+            outdir=$outdir[1, -5]
+        }
+
+        if [[ -e $outdir ]] {
+            outdir="$(mktemp -d -p $PWD x-XXX)"
+        } else {
+            mkdir $outdir
+        }
+
+        case $(get_type_by_name $i || get_type_by_file $i) {
+            (7z|7z_r)
+            7z x $i -o$outdir
+            ;;
+
+            (tar)
+            tar -xavf $i -C $outdir
+            ;;
+
+            (cpio|cpio_r)
+            local file_path=$i
+            [[ $i != /* ]] && file_path=$PWD/$i
+            cd $outdir && cpio -iv < $file_path && cd ..
+            ;;
+
+            (gz)
+            zcat $i > $outdir/$i[1,-4]
+            ;;
+
+            (xz)
+            xzcat $i > $outdir/$i[1,-4]
+            ;;
+
+            (bz2)
+            bzcat $i > $outdir/$i[1,-5]
+            ;;
+
+            (lzma)
+            lzcat $i > $outdir/$i[1,-6]
+            ;;
+
+            (lz4)
+            lz4cat $i > $outdir/$i[1,-5]
+            ;;
+
+            (ar)
+            local file_path=$i
+            [[ $i != /* ]] && file_path=$PWD/$i
+            cd $outdir && ar x $file_path && cd ..
+            ;;
+
+            (*)
+            echo $i: error
+            ;;
+        }
+
+        local files=$(ls -A $outdir)
+
+        if [[ -z $files ]] {
+            rmdir $outdir
+        } elif [[ -e $outdir/$files && ! -e $files ]] {
+            mv -v $outdir/$files . && rmdir $outdir
+            echo $i " -> " $files
+        } else {
+            echo $i " -> " $outdir
+        }
+    }
+    ;;
+
+    (*)
+    echo error
+    return 1
+    ;;
+}
+```
+
 ### 总结
 
 本文讲解了几个简单的 zsh 脚本,后续可能会补充更多个。
+
+### 更新历史
+
+2017.09.13:新增“实例七:统一压缩解压工具”。