寫個批處理指令碼來幫忙幹活---遍歷資料夾&字串處理

請叫我大蘇發表於2018-05-18

這次打算寫幾篇關於指令碼方面的部落格,主要是記錄一下 Gradle 指令碼和批處理指令碼的一些寫法,方便後續查閱。

前言

平常開發過程中,一些較為重複的手工性工作,如果能讓指令碼來幫忙處理,自然是最好的,剛好之前有些工作有點過於重複且都是手工性去完成,所以就想著能否寫個指令碼來處理。

因為我還是用的 windows 開發,所以最開始想到的就是批處理指令碼,但寫完後發現,重複性工作是可以交給指令碼去處理了,但每次要執行這個指令碼檔案還得開啟指令碼所在的資料夾找到指令碼點選去執行。

emmm,因為我是開發 Android 的,電腦開機時 Android Stuido 就沒關閉過,然後又想到 Gradle 的指令碼可以直接通過 AS 來點選執行,這樣一來,執行指令碼,也就是敲程式碼過程中隨手一個快捷鍵就搞定,簡單、方便。

所以,這篇就稍微來記錄下批處理指令碼和 Gradle 指令碼的一些寫法,很基礎簡單,因為我的需求就是執行 java 命令來對某個資料夾下的 apk 檔案分別進行簽名,而後輸出新的命名方式的 apk 檔案。

所以,指令碼涉及到的操作也就只是資料夾的遍歷、字串的處理、命令的執行這幾個方面而已,後續有新接觸再慢慢補充。

批處理指令碼

1. 遍歷指定資料夾下的檔案

1.1 命令解釋

命令: for [引數] %%變數名 in (匹配符) do (執行的命令)

切記:每個指令之間必須以空格隔開,in 與 ( 之間有空格,do 與 ( 間也有空格,否則命令會無法成功執行

ps:本節只講用批處理指令碼執行 for 命令遍歷資料夾的場景,因此以下分析每個指令意義時,不介紹其他含義

[]:表示此項指令為可選

[引數]:引數取值一共有四種: /d, /r, /l, /f,加上無引數,所以一共五種場景

  • 無參:遍歷當前路徑的資料夾下的檔案,但也可在(匹配符)中指定路徑
  • /d:遍歷當前路徑的資料夾下的資料夾,但也可在(匹配符)中指定路徑
  • /r [路徑]:深度遍歷指定路徑下的所有檔案,子目錄中的檔案也會被遍歷到,如果沒指定路徑,預設當前路徑
  • /l :當使用引數 /l 時,需結合(匹配符)一起使用,此時 () 括號內部的用法規則為:(start, step, end),此時的 for 命令作用等同於 java 語言中的 for 語句
  • /f :用於解析檔案中的內容,本節不做介紹

%%變數名:作用類似於 for(int i = 0; ; ) 中的 int i = 0,有些區別點的就是,批處理的 for 迴圈遍歷每一個子項時,%%變數名 <=> 每個子項,即 &&變數名 已經是指向具體的每個子項了

(匹配符):在 in 指令之後 () 括號裡的內容可表示為萬用字元,用於按照指定的規則過濾資料夾下的檔案,如 (*.txt) 表示遍歷資料夾內所有以 .txt 結尾的檔案

(執行的命令):前面的指令就可以取到資料夾內指定的每個子項了,那麼接下去要對每個子項如何操作,就在這裡寫,類似於 java 的 for 命令後的 {} 大括號的作用

1.2 使用示例

當前目錄.png

以下示例基於上圖中的檔案路徑,批處理指令碼為 test.bat

  • 無參:for %%i in (*) do ( echo %%i )

for無參命令示例.png

效果:遍歷當前目錄下的所有檔案

  • 無參指定路徑:for %%i in (c:\softwares\VisualBat\*.url) do ( echo %%i )

for無參指定路徑命令示例.png

效果:遍歷在(匹配符)中指定路徑下的以 .url 結尾的檔案

  • 帶引數 /d:for /d %%i in (*) do ( echo %%i )

for引數d命令示例.png

效果:遍歷當前目錄下所有的資料夾

  • 帶引數 /d 指定路徑:for /d %%i in (c:\softwares\VisualBat\*) do ( echo %%i )

for引數d指定路徑命令示例.png

效果:遍歷指定目錄下的所有資料夾,%%i 指向每個子資料夾的絕對路徑

  • 帶引數 /r :for /r %%i in (*.url) do ( echo %%i )

for引數r命令示例.png

效果:深度遍歷當前路徑下所有以 .url 結尾的檔案,因為是深度遍歷,因此 %%i 指向檔案的絕對路徑

  • 帶引數 /r 指定路徑:for /r c:\softwares\VisualBat\ %%i in (*.url) do ( echo %%i )

    效果:同上圖

  • 帶引數 /l :for /l %%i in (1, 1, 5) do ( echo %%i )

for引數l命令示例.png

效果:等效於 java 中的 for (int i = 1; i <= 5; i++)語句,起始值,遞增或遞減,終止值都可自行設定

  • 帶引數 /d /r:for /d /r %%i in (*) do ( echo %%i )

for引數dr命令示例.png

效果:引數可結合使用,/d 表示遍歷資料夾,/r 表示深度遍歷,因此以上命令作用為深度遍歷當前目錄下的所有資料夾,包括子目錄中的資料夾

2. 臨時變數的使用

2.1 變數的基本用法

命令:set key=value

切記:key=value 三者之間絕對不能出現空格,不能為了像遵守 java 風格擅自給新增上空格,這與 java 的 int a = 1 宣告變數不同,切記

變數使用:%key%

示例

@echo off
set name=dasuAndroidTv
echo %name%
複製程式碼

set命令示例.png

效果:name 可當做臨時變數使用,使用時需用 %% 將變數名括起來使用

侷限:不允許在 for 命令中類似上步中宣告變數並直接使用,如下:

@echo off
for /l %%i in (0,1,5) do (
    set name=dasuAndroidTv
    echo %name%
)
複製程式碼

set命令示例2.png

效果:在 for 命令中宣告臨時變數,並直接通過 %key% 方式使用時會出現上圖中的錯誤:ECHO 處於關閉狀態,但如果 set key=value 臨時變數的宣告是放在 for 命令外部,for 命令內部只是使用的話,是可以的,如下:

@echo off
set name=dasuAndroidTv
for /l %%i in (0,1,5) do (
    echo %name%
)
複製程式碼

set命令示例3.png

效果:在 for 命令外部宣告臨時變數,for 命令內部只是使用,這種方式是允許的

2.2 變數在 for 命令中的用法

提問:那麼如果要在 for 命令中才宣告臨時變數,並使用的話,該如何做?

for 命令中臨時變數的使用:

  1. 需啟用變數延遲功能,命令:setlocal enabledelayedexpansion
  2. for 命令中的臨時變數使用時用 !key! 感漢號括起來的形式代替 %key%
  3. 理由:不清楚,google 來的解決方案,感興趣想深入研究的自行搜尋

示例

@echo off
setlocal enabledelayedexpansion
set name=dasu
for /l %%i in (0, 1, 5) do (
    set name=dasuAndroidTv 
    echo !name!
    echo %name%
)
複製程式碼

set命令示例4.png

效果:說得白一點,在 for 命令中通過 %name% 方式使用的臨時變數,取的 name 這個臨時變數的值會一直是它在 for 命令外賦值的內容,即使在 for 命令中通過 set 命令對這個變數又重新賦值,也不會生效。

那麼,如果需要在 for 命令中通過 set 命令賦值後的臨時變數能夠馬上拿來使用,需要兩個步驟,一在檔案開頭啟用變數延遲功能,命令:setlocal enabledelayedexpansion,二在 for 命令中通過 **!name!**方式來使用臨時變數。

3. 字串處理

3.1 擷取

命令:%key:~[start,num]%

解釋:當 %key% 中出現了 :~,則表示要對 key 指向的這個字串做擷取操作,擷取操作支援以下幾種形式:

  • 擷取指定位置開始的 n 個字串%key:~0,4%,表示擷取從下標 0 開始的之後 4 個字元
  • 擷取從指定位置開始的整個字串%key:~4%,表示擷取從下標為 4 開始的整個字串
  • 擷取通過倒數方式指定開始位置的整個字串%key:~-2%,表示擷取從倒數第 2 個字元開始的整個字串
  • 擷取通過倒數方式指定位置開始之後的 n 個字串%key:-4,2%,表示擷取從倒數第 4 個字元開始的 2 個字元
  • 正數倒數方式相結合:%key:~2,-2%,表示擷取從下標 2 開始到倒數第 2 個之間的字串

示例

@echo off
rem (rem表示後面是註釋的內容,類似於 java //)原始字串
set name=dasuAndroidTv

rem 註釋內容:表示擷取從下標 0 開始的之後 4 個字元,輸出 dasu
echo %name:~0,4%

rem 註釋內容:表示擷取從下標為 4 開始的整個字串,輸出 AndroidTv
echo %name:~4%  

rem 註釋內容:表示擷取從倒數第 2 個字元開始的整個字串,輸出 Tv
echo %name:~-2%

rem 註釋內容:表示擷取從倒數第 4 個字元開始的 2 個字元,輸出 Android
echo %name:~4,-2%

rem 註釋內容:表示擷取從下標 2 開始到倒數第 2 個之間的字串,輸出 id
echo %name:~-4,2%
複製程式碼

字串擷取命令示例.png

3.2 拼接

命令:%key1%%key2%

解釋:將要拼接的那個字串直接跟在被拼接的後面即可,不需要任何拼接操作符

示例

@echo off
set name1=dasu
set name2=AndroidTv
echo %name1%%name2%  
rem 這裡是註釋內容:輸出 dasuAndroidTv
複製程式碼

字串擷取命令示例2.png

3.3 替換

命令:%key:被替換字串=替換的字串%

解釋:不解釋了,直接看示例,很容易明白

示例

@echo off
set name=whoAndroidTv
echo %name:who=dasu%
rem 這裡是註釋內容:輸出 dasuAndroid
複製程式碼

字串替換命令示例.png

3.4 檔案特殊操作

如果是在 for 命令中遍歷了某個資料夾下的檔案,那麼此時可以通過一些特殊命令來獲取這個檔案的各種資訊,直接看示例:

@echo off
for %%i in (*.txt) do (
   echo %%i
   echo %%~fi
   echo %%~di
   echo %%~pi
   echo %%~ni
   echo %%~xi
   
   echo %%~ti
   echo %%~zi
)
複製程式碼

特殊命令示例.png

解釋: 在通過 for 命令遍歷檔案時,%%i 根據不同的 for 使用方式,內容也有所不同,具體見第 1 節。在上述這種用法下,%%i 指向了當前目錄下每個檔名,完整的檔名。

那麼,此時就可以通過一些特殊命令來取得檔案的相關資訊,比如:

  • %%~fi:表示獲取該檔案的絕對路徑資訊
  • %%~di:表示獲取該檔案所在的碟符
  • %%~pi:表示獲取該檔案的路徑,不包含碟符的資訊
  • %%~ni:表示獲取該檔案的檔名,不包含副檔名資訊
  • %%~xi:表示獲取該檔案的副檔名
  • %%~ti:表示獲取該檔案的上次修改時間
  • %%~zi:表示獲取該檔案的大小

4. 完整示例

最後,我們來個具體場景,將本篇所學的知識用上一遍,鞏固一下。

場景:遍歷指定路徑目錄下的所有 apk 檔案,並通過一個 sign.jar 檔案,分別對每個 apk 檔案執行 java 命令來進行簽名工作,sign.jar 接收兩個引數,一個是需要簽名的 apk,另外一個為輸出的 apk,要求籤名後的 apk 命名方式為將原檔名中的 unsign 替換成 google,並輸出在跟 apk 同一個目錄內即可。

完整示例.png

apk 路徑:c:\users\suxq\desktop\outputs

sign.jar 路徑:c:\users\suxq\desktop

java 簽名命令示例(要求 sign.jar 和 apk 檔案都在同一路徑下,即可用如下命令):

java -jar sign.jar meizi_1_3_0_debug_unsign.apk meizi_1_3_0_debug_google.apk

批處理指令碼程式碼:

@echo off
setlocal enabledelayedexpansion

set sign=c:\users\suxq\desktop\sign.jar
set apkPath=c:\users\suxq\desktop\outputs\

for %%i in (%apkPath%*.apk) do (
    set oldApk=%%~nxi
    set outApk=!oldApk:unsign=google!
    echo java -jar %sign% !oldApk! !outApk!
    rem 這裡是註釋內容:由於 apk 檔案 和 sign.jar 檔案都是虛擬的,因此真正執行時會報錯,這裡就只是將 java 整句命令輸出,從整句命令就可以確認是否會正確執行,如果這些檔案都是真的話。真的指令碼應該將 echo 去掉
)
複製程式碼

完整示例2.png

效果:完美~

首先,遍歷指定目錄下的檔案達到了,而且可以對檔名字串進行處理,替換其中一些值,最後,可以根據指定位置的 sign.jar 檔案,通過 java 命令來執行簽名工作。

這個場景,剛好把我們今天學的關於批處理的遍歷資料夾操作、臨時變數使用、字串的處理三者都包括在內,感興趣的也去試試看吧~


QQ圖片20180316094923.jpg
最近(2018-03)剛開通了公眾號,想激勵自己堅持寫作下去,初期主要分享原創的Android或Android-Tv方面的小知識,準備可能還有點不足,感興趣的可以先點一波關注,謝謝支援~~

相關文章