Zsh 開發指南(第十九篇 腳本實例講解)

導讀

本文將講解一些比較簡單的 zsh 腳本實例。git

實例一:複製一個目錄的目錄結構

功能:github

將一個目錄及它下邊的全部目錄複製到另外一個目錄中(即建立同名目錄),但不復制目錄下的其餘類型文件。數組

例子:bash

src 的目錄結構:

src
├── a
├── b
│   ├── 1.txt
│   └── 2
│       └── 3.txt
├── c.txt
├── d
├── e f
│   └── g
│       └── 4.txt
└── g h -> e f

要構造一個 dst 目錄,只包含 src 下的目錄,內容以下:

dst
└── src
    ├── a
    ├── b
    │   └── 2
    ├── d
    └── e f
        └── g複製代碼

思路:微信

  1. 首先須要先將 src 目錄下的目錄名篩選出來,能夠用 **/*(/) 匹配。
  2. 而後用 mkdir -p 在 dst 目錄中建立對應的目錄。
# 參數 1:src 目錄
# 參數 2:待建立的 dst 目錄

#!/bin/zsh 
for i ($1/**/*(/)) {
    # -p 參數是遞歸建立目錄,這樣不用考慮目錄的建立順序
    mkdir -p $2/$i
}複製代碼

實例二:尋找不配對的文件

功能:併發

須要當前目錄下有一些 .txt 和 .txt.md5sum 的文件,須要尋找出沒有對應的 .md5sum 文件的 .txt 文件。(實際的場景是尋找已經下載完成的文件,未下載完的文件都對應某個帶後綴的文件。)socket

例子:ide

當前目錄的全部文件:

aa.txt
bb.txt
bb.txt.md5sum
cc dd.txt
cc dd.txt.md5sum
ee ff.txt.md5sum
gg.txt
hh ii.txt

須要找出沒有對應 .md5sum 的 .txt 文件:
aa.txt
gg.txt
hh ii.txt複製代碼

思路:函數

  1. 找到全部 .md5sum 文件,而後把文件名中的 .md5sum 去掉,即爲那些須要排除的 .txt 文件(a)。
  2. 全部的文件,排除掉 .m5sum 文件,再排除掉 a,即結果。

實現:工具

#!/bin/zsh 
all_files=(*)
bad_files=(*.md5sum)
bad_files+=(${bad_files/.md5sum})

# 數組差集操做
echo ${all_files:|bad_files}複製代碼

實例三:用 sed 批量重命名文件

功能:

用形如 sed 命令的用法批量重命名文件。

例子:

# 實現 renamex 命令,接受的第一個參數爲 sed 的主體參數,其他參數是文件列表
# 效果是根據 sed 對文件名的修改重命名這些文件

% tree
.
├── aaa_aaa.txt
├── aaa.txt
├── ccc.txt
└── xxx
    ├── aaa bbb.txt
    └── bbb ccc.txt

% renamex s/aaa/bbb/g **/*
'aaa_aaa.txt' -> 'bbb_bbb.txt'
'aaa.txt' -> 'bbb.txt'
'xxx/aaa bbb.txt' -> 'xxx/bbb bbb.txt'

% tree
.
├── bbb_bbb.txt
├── bbb.txt
├── ccc.txt
└── xxx
    ├── bbb bbb.txt
    └── bbb ccc.txt複製代碼

思路:

  1. 要找出全部的文件名,而後用 sed 替換成新文件名。
  2. 若是文件名有變化,用 mv 命令移動

實現:

#!/bin/zsh 
(($+2)) || {
    echo 'Usage: renamex s/aaa/bbb/g *.txt'
    return
}

for name ($*[2,-1]) {
    local new_name="$(echo $name | sed $1)"
    [[ $name == $new_name ]] && continue
    mv -v $name $new_name
}複製代碼

實例四:根據文件的 md5 刪除重複文件

功能:

刪除當前目錄以及子目錄下全部的重複文件(根據 md5 判斷,不是很嚴謹)。

思路:

  1. 用 md5sum 命令計算全部文件的 md5。
  2. 使用哈希表判斷 md5 是否重複,刪除哈希表裏已經有 md5 的後續文件。

實現:

#!/bin/zsh 
# D 是包含以 . 開頭的隱藏文件
local files=("${(f)$(md5sum **/*(.D))}")
local files_to_delete=()
local -A md5s

for i ($files) {
    # 取前 32 位,即 md5 的長度
    local md5=$i[1,32]

    if (($+md5s[$md5])) {
        # 取 35 位以後的內容,即文件路徑,md5 後邊有兩個空格
        files_to_delete+=($i[35,-1])
    } else {
        md5s[$md5]=1
    }
}

(($#files_to_delete)) && rm -v $files_to_delete複製代碼

實例五:轉換 100 之內的漢字數字爲阿拉伯數字

功能:

轉換 100 之內的漢字數字爲阿拉伯數字,如六十八轉換成 68。

思路:

  1. 建一個哈希表存放漢字與數字的對應關係。
  2. 比較麻煩的是「十」,在不一樣的位置,轉換成的數字不一樣,須要分別處理。

實現:

#!/bin/zsh 
local -A table=(
零 0
一 1
二 2
三 3
四 4
五 5
六 6
七 7
八 8
九 9
)

local result

if [[ $1 == 十 ]] {
    result=一零
} elif [[ $1 == 十* ]] {
    result=${1/十/一}
} elif [[ $1 == *十 ]] {
    result=${1/十/零}
} elif [[ $1 == *十* ]] {
    result=${1/十}
} else {
    result=$1
}

for i ({1..$#result}) {
    result[i]=$table[$result[i]]

    if [[ -z $result[i] ]] {
        echo error
        return 1
    }
}

echo $result

運行結果:

% ./convert 一
1
% ./convert 十
10
% ./convert 十五
15
% ./convert 二十
20
% ./convert 五十六
56
% ./convert 一百
error複製代碼

實例六:爲帶中文漢字數字的文件名重命名成以對應數字開頭

功能:

見下邊例子。

例子:

當前目錄有以下文件:

Zsh-開發指南(第一篇-變量和語句).md
Zsh-開發指南(第七篇-數值計算).md
Zsh-開發指南(第三篇-字符串處理之轉義字符和格式化輸出).md
Zsh-開發指南(第九篇-函數和腳本).md
Zsh-開發指南(第二篇-字符串處理之經常使用操做).md
Zsh-開發指南(第五篇-數組).md
Zsh-開發指南(第八篇-變量修飾語).md
Zsh-開發指南(第六篇-哈希表).md
Zsh-開發指南(第十一篇-變量的進階內容).md
Zsh-開發指南(第十七篇-使用-socket-文件和-TCP-實現進程間通訊).md
Zsh-開發指南(第十三篇-管道和重定向).md
Zsh-開發指南(第十九篇-腳本實例講解).md
Zsh-開發指南(第十二篇-[[-]]-的用法).md
Zsh-開發指南(第十五篇-進程與做業控制).md
Zsh-開發指南(第十八篇-更多內置模塊的用法).md
Zsh-開發指南(第十六篇-alias-和-eval-的用法).md
Zsh-開發指南(第十四篇-文件讀寫).md
Zsh-開發指南(第十篇-文件查找和批量處理).md
Zsh-開發指南(第四篇-字符串處理之通配符).md

須要重命名成這樣:

01_Zsh-開發指南(第一篇-變量和語句).md
02_Zsh-開發指南(第二篇-字符串處理之經常使用操做).md
03_Zsh-開發指南(第三篇-字符串處理之轉義字符和格式化輸出).md
04_Zsh-開發指南(第四篇-字符串處理之通配符).md
05_Zsh-開發指南(第五篇-數組).md
06_Zsh-開發指南(第六篇-哈希表).md
07_Zsh-開發指南(第七篇-數值計算).md
08_Zsh-開發指南(第八篇-變量修飾語).md
09_Zsh-開發指南(第九篇-函數和腳本).md
10_Zsh-開發指南(第十篇-文件查找和批量處理).md
11_Zsh-開發指南(第十一篇-變量的進階內容).md
12_Zsh-開發指南(第十二篇-[[-]]-的用法).md
13_Zsh-開發指南(第十三篇-管道和重定向).md
14_Zsh-開發指南(第十四篇-文件讀寫).md
15_Zsh-開發指南(第十五篇-進程與做業控制).md
16_Zsh-開發指南(第十六篇-alias-和-eval-的用法).md
17_Zsh-開發指南(第十七篇-使用-socket-文件和-TCP-實現進程間通訊).md
18_Zsh-開發指南(第十八篇-更多內置模塊的用法).md
19_Zsh-開發指南(第十九篇-腳本實例講解).md複製代碼

思路:

  1. 首先須要寫將漢字數字轉成阿拉伯數字的函數。
  2. 而後須要從文件名中截取漢字數字,而後轉成阿拉伯數字。
  3. 拼接文件名,而後移動文件。

實現:

#!/bin/zsh 
# 轉換數字的邏輯和上一個實例同樣

local -A table=(
零 0
一 1
二 2
三 3
四 4
五 5
六 6
七 7
八 8
九 9
)

convert() {
    local result

    if [[ $1 == 十 ]] {
        result=一零
    } elif [[ $1 == 十* ]] {
        result=${1/十/一}
    } elif [[ $1 == *十 ]] {
        result=${1/十/零}
    } elif [[ $1 == *十* ]] {
        result=${1/十}
    } else {
        result=$1
    }

    for i ({1..$#result}) {
        result[i]=$table[$result[i]]

        if [[ -z $result[i] ]] {
            echo error
            return 1
        }
    }

    echo $result
}

for i (Zsh*.md) {
    # -Z 2 是爲了在前邊補全一個 0
    # 把文件名「第」以前和「篇」以後的所有去除
    local -Z 2 num=$(convert ${${i#*第}%篇*})
    mv -v $i ${num}_$i
}複製代碼

實例七:統一壓縮解壓工具

功能:

Linux 下經常使用的壓縮、歸檔格式衆多,參數各異,寫一個用法統一的壓縮解壓工具,用於建立、解壓 .zip .7z .tar .tgz .tbz2 .txz .tar.gz .tar.bz2 .tar.xz .cpio .ar .gz .bz2 .xz 等文件。(相似 atool,但 atool 好久沒更新了,一些新的格式不支持,無法定製。並且是用 perl 寫的,很難看懂。因此仍是決定本身寫一個,只覆蓋 atool 的一部分經常使用功能。)

例子:

# 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
    ;;
}複製代碼

實例八:方便併發運行命令的工具

功能:

咱們常常會遇到在循環裏批量處理文件的場景(好比將全部 jpg 圖片轉換成 png 圖片),那麼就會遇到一個麻煩:若是在前臺處理文件,那同一時間只能處理一個,效率過低;若是在後臺處理文件,那麼瞬間就會啓動不少個進程,佔用大量資源,系統難以承受。咱們但願的是在同一時間最多同時處理固定數量(好比 10 個)的文件,若是已經達到了這個數量,那麼就先等一會,直到有退出的進程後再繼續。parallel 命令中在必定程度上能知足這個需求,但用起來太麻煩。

例子:

# rr 是一個函數(可放在 .zshrc 中),直接 rr 加命令便可使用
# 命令中支持變量、重定向等等,格式上和直接輸入命令沒有區別(不支持 alias)
% rr sleep 5
[4] 5031
% rr sleep 5
[5] 5032

# 若是不加參數,則顯示當前運行的進程數、最大進程併發數和運行中進程的進程號
# 默認最大進程併發數是 10
% rr
running/max: 2/10
pid: 5031 5032
# 5 秒以後,運行結束
% rr
running/max: 0/10


# 用 -j 來指定最大進程併發數,指定一次便可,如需修改可再次指定
# 能夠只調整最大進程併發數而不運行命令
% rr -j2 sleep 10
[4] 5035
% rr sleep 10
[5] 5036

# 超過了最大進程併發數,等待,而且每一秒檢查一次是否有進程退出
# 若是有進程退出,則繼續在後臺運行當前命令
% rr sleep 10
running/max: 2/2, wait 1s ...
pid: 5035 5036
running/max: 2/2, wait 1s ...
pid: 5035 5036
[4]  - done       $*
[4] 5039


# 實際使用場景,批量將 jpg 圖片轉換成 png 圖片,gm 是 graphicsmagick 中的命令
# 轉換圖片格式比較耗時,順序執行的話須要好久
% for i (*.jpg) { rr gm convert $i ${i/jpg/png} }
[4] 5055
[5] 5056
[6] 5057
[7] 5058
[8] 5059
[9] 5060
[10] 5061
[11] 5062
[12] 5063
[13] 5064
running/max: 10/10, wait 1s ...
pid: 5060 5061 5062 5063 5064 5055 5056 5057 5058 5059
running/max: 10/10, wait 1s ...
pid: 5060 5061 5062 5063 5064 5055 5056 5057 5058 5059
[11]    done       $*
[5]    done       $*
[5] 5067
[12]    done       $*
[11] 5068
[6]    done       $*
[6] 5069
[12] 5070
running/max: 10/10, wait 1s ...
pid: 5070 5060 5061 5064 5055 5067 5068 5069 5058 5059
[13]  - done       $*
[4]    done       $*
[4] 5072
[13] 5073
running/max: 10/10, wait 1s ...
pid: 5070 5060 5072 5061 5073 5067 5068 5069 5058 5059
[5]    done       $*
[6]    done       $*
[5] 5075
[6] 5076
running/max: 10/10, wait 1s ...
pid: 5070 5060 5072 5061 5073 5075 5076 5068 5058 5059
...複製代碼

思路:

  1. 須要在全局變量裏記錄最大進程併發數和當前運行的進程(哈希表)。
  2. 每運行一個進程,將對應的進程號放入哈希表中。
  3. 若是當前運行進程數達到最大進程併發數,則循環檢查哈希表裏的進程是否退出。

實現:

rr() {
    (($+max_process)) || typeset -g max_process=10
    (($+running_process)) || typeset -gA running_process=()

    [[ $1 == -j<1-> ]] && {
        max_process=${1[3,-1]}
        shift
    }

    (($# == 0)) && {
        for i (${(k)running_process}) {
            [[ -e /proc/$i ]] || unset "running_process[$i]"
        }

        echo "running/max: $#running_process/$max_process"
        (($#running_process > 0)) && echo "pid: ${(k)running_process}"
        return
    }

    while ((1)) {
        local running_process_num=$#running_process

        if (($running_process_num < max_process)) {
            $* &
            running_process[$!]=1
            return
        }

        for i (${(k)running_process}) {
            [[ -e /proc/$i ]] || unset "running_process[$i]"
        }

        (($#running_process == $running_process_num)) && {
            echo "running/max: $running_process_num/$max_process, wait 1s ..."
            echo "pid: ${(k)running_process}"
            sleep 1
        }
    }
}複製代碼

實例九:批量轉換圖片格式

功能:

將當前目錄及子目錄的全部常見圖片格式轉換成 jpg 格式(jpg 格式也要轉換一遍,能夠減小文件體積),而後刪除原圖片。須要用 5 個併發進程來處理。注意避免僅擴展名不一樣的文件互相覆蓋的狀況。

例子:

% tree
.
├── mine
│   ├── 信.txt
│   ├── 第一封信.jpg
│   └── 第二封信.JPG
├── 搞笑
│   ├── 賣萌.GIF
│   ├── 貓吃魚.gif
│   └── 貓搶東西吃.gif
└── 素材
    ├── 104 按鍵模板.jpg
    ├── 104 按鍵模板.psd
    ├── ahk
    │   ├── ahk_bg.jpg
    │   ├── ahk_home_logo.jpg
    │   ├── ahk_home_logo.txt
    │   ├── ahk_home_qr.jpg
    │   ├── ahk_home_qr_small.jpg
    │   └── ahk_logo.png
    ├── stp_fc_cw_png_pk
    │   ├── HD.PNG
    │   ├── newimage.png
    │   ├── nshd.PNG
    │   └── std.png
    ├── 地球.jpg
    ├── 星系.JPEG
    ├── 木紋 背景.GIF
    ├── 木紋 背景.jpeg
    └── 木紋 背景.jpg

5 directories, 23 files

% alltojpg
running/max: 0/5
running: 5, wait 1.0000000000s ...
pid: 5953 5954 5955 5956 5957
running: 5, wait 1.0000000000s ...
pid: 5965 5966 5967 5968 5959

% tree
.
├── mine
│   ├── 信.txt
│   ├── 第一封信.jpg
│   └── 第二封信.jpg
├── 搞笑
│   ├── 賣萌_g.jpg
│   ├── 貓吃魚_g.jpg
│   └── 貓搶東西吃_g.jpg
└── 素材
    ├── 104 按鍵模板.jpg
    ├── 104 按鍵模板.psd
    ├── ahk
    │   ├── ahk_bg.jpg
    │   ├── ahk_home_logo.jpg
    │   ├── ahk_home_logo.txt
    │   ├── ahk_home_qr.jpg
    │   ├── ahk_home_qr_small.jpg
    │   └── ahk_logo_p.jpg
    ├── stp_fc_cw_png_pk
    │   ├── HD_p.jpg
    │   ├── newimage_p.jpg
    │   ├── nshd_p.jpg
    │   └── std_p.jpg
    ├── 地球.jpg
    ├── 星系_e.jpg
    ├── 木紋 背景_e.jpg
    ├── 木紋 背景_g.jpg
    └── 木紋 背景.jpg

5 directories, 23 files複製代碼

思路:

  1. 併發運行命令的方法見上一個實例。
  2. 轉換圖片格式用 gm convert 命令(graphicsmagick 中)或者 convert 命令(imagemagick 中)。
  3. 常見的圖片文件擴展名有 jpg jpeg png gif,另外多是大寫的擴展名。
  4. 爲了不相似 a.gif 覆蓋 a.jpg 的狀況,爲不一樣的文件格式添加不一樣後綴,這樣能夠無需檢查是否有同名文件,加快速度。

實現:

#!/bin/zsh 
# rr 是上一個實例中代碼的改進版本
rr() {
    (($+max_process)) || typeset -gi max_process=10
    (($+check_interval)) || typeset -gF check_interval=1
    (($+running_process)) || typeset -gA running_process=()

    while {getopts i:j:h arg} {
        case $arg {
            (i)
            ((OPTARG > 0)) && check_interval=$OPTARG
            ;;

            (j)
            ((OPTARG > 0)) && max_process=$OPTARG
            ;;

            (h)
            echo "Usage: $0 [-i check_interval] [-j max_process] [cmd] [args]"
            return
            ;;
        }
    }

    shift $((OPTIND - 1))

    (($# == 0)) && {
        for i (${(k)running_process}) {
            [[ -e /proc/$i ]] || unset "running_process[$i]"
        }

        echo "running/max: $#running_process/$max_process"
        (($#running_process > 0)) && echo "pid: ${(k)running_process}"
        return 0
    }

    while ((1)) {
        local running_process_num=$#running_process

        if (($running_process_num < max_process)) {
            $* &
            running_process[$!]=1
            return
        }

        for i (${(k)running_process}) {
            [[ -e /proc/$i ]] || unset "running_process[$i]"
        }

        (($#running_process == $running_process_num)) && {
            echo "running: $running_process_num, wait ${check_interval}s ..."
            echo "pid: ${(k)running_process}"
            sleep $check_interval
        }
    }
}


# JPG 做爲中間擴展名
rename .JPG .jpg **/*.JPG

# 設置進程併發數爲 5
rr -j5

for i (**/*.(jpg|png|PNG|jpeg|JPEG|gif|GIF)) {
    rr gm convert $i $i.JPG
}

# 等全部操做結束
wait

# 刪除原文件
rm **/*.(jpg|png|PNG|jpeg|JPEG|gif|GIF)

# 避免覆蓋同名文件
rename .jpg.JPG .jpg **/*.JPG
rename .png.JPG _p.jpg **/*.JPG
rename .PNG.JPG _p.jpg **/*.JPG
rename .jpeg.JPG _e.jpg **/*.JPG
rename .JPEG.JPG _e.jpg **/*.JPG
rename .gif.JPG _g.jpg **/*.JPG
rename .GIF.JPG _g.jpg **/*.JPG複製代碼

總結

本文講解了幾個比較實用的 zsh 腳本,後續可能會補充更多個。

全系列文章地址:github.com/goreliu/zsh…

付費解決 Windows、Linux、Shell、C、C++、AHK、Python、JavaScript、Lua 等領域相關問題,靈活訂價,歡迎諮詢,微信 ly50247。

相關文章
相關標籤/搜索