写完批处理脚本,再写个Gradle脚本,解放双手

前言

上一篇写个批处理来帮忙干活---遍历&字符串处理中,我们已经学习如何写批处理脚本来帮我们做一些简单的重复性工作,本篇继续来学习如何用 Gradle 写脚本,让它也来帮我们干活

Gradle 脚本

需求场景跟上一篇一样,只是需要脚本能够帮我们遍历某个目录下的文件,然后分别针对每个文件执行 java 命令,再输出新的命名格式的文件即可,因此脚本涉及的方面仍然是:文件夹的遍历操作、字符串处理、执行 java 命令。下面开始学习吧:

1. 遍历指定文件夹下的文件

1.1 files()

命令

files(file1, file2, file3, file4...) .each {file ->
    println file.name
}

解释:files() 方法可以理解成一个集合,通过参数往集合中添加元素,只要能将需要遍历的目录下的所有文件都通过参数,传给 files(),那么就可以直接通过 .each 来遍历集合中的每个元素,达到遍历文件夹的目的

示例

def dir = new File("C:\Users\suxq\Desktop\outputs")
files(dir.listFiles()).each { file ->
    println file.name
}

解释:可以结合 File 的 listFiles() 方法使用,这个方法刚好可以返回整个目录下的文件,刚好作为参数传给 files(),这样一来就可以达到遍历文件夹的目的了。

过滤:如果只想遍历目录下符合规则的文件,那么可以自定义过滤规则:

def outputs = file("C:\\Users\\suxq\\Desktop\\outputs")
files(dir.listFiles(new FilenameFilter() {
        @Override
        boolean accept(File dir, String name) {
            //自定义过滤规则
            return name.endsWith(".apk")
        }
    }))
.each { file ->
    println file.name
}    
1.2 fileTree()

命令

fileTree(dirPath).each { file ->
    println file.name
}

解释:fileTree 使用会比 files 更简单,只需要传入目录的路径,即可对目录下的文件进行遍历

示例

def outputs = file("C:\\Users\\suxq\\Desktop\\outputs")
fileTree(outputs).each { file ->
    println file.name
}

过滤:如果不想遍历整个目录,那么 fileTree 方式也很容易自定义过滤规则:

def outputs = file("C:\\Users\\suxq\\Desktop\\outputs")
fileTree(outputs){
    //自定义过滤规则
    include "*.apk"
}
.each { file ->
    println file.name
}

解释:fileTrss 的自定义过滤规则使用也很方便

注意:以上示例代码中,涉及到一些 groovy 语言的语法结构,Gradle 是基于 groovy 开发的,groovy 有一个闭包的概念,另外,groovy 支持方法的括号省略,方法的最后一个参数外移等特性,所以,如果上述代码看得不是很懂的话,可以到我之前写的一篇介绍 groovy 基础语法的博客看看:学点Groovy来理解build.gradle代码

1.3 java 实现

由于 Gradle 是基于 groovy 开发的,而 groovy 又是基于 java 开发的,因此,想要遍历指定目录下的文件,你也可以完全用 java 来实现,照样能在 Gradle 脚本中运行,java 实现的就不给示例了

2. 字符串处理

由于 Gradle 基于 groovy 开发,而 groovy 又是基于 java 开发的,因此,对字符串的处理完全可以使用 java 的方式,如通过 +来拼接,或者通过 StringBuffer 对象来操作,或者直接使用 String 的 api 都可以。

所以,这一节就主要来讲讲,在 groovy 中可以表示为字符串的格式。

java 只支持用 "xxx" 双引号来表示字符串

groovy 支持使用 ‘xxx‘, "xxx", ‘‘‘xxx‘‘‘, """xxx""", /xxx/, $/xxx/$ 即单引号,双引号等6种方法来表示字符串

它们之间的区别为:‘xxx‘, "xxx" 只支持单行字符串,不支持多行,剩下的四种都支持多行字符串,如下图

斜杠我也很少见,常见的是带有 ${} 的字符串,比如: println "blog‘s url: ${blogUrl}" 这是 groovy 的 GString 特性,支持字符串插值,有点了类似于变量引用的概念,但注意,在 ‘...‘, ‘‘‘...‘‘‘ 单引号表示的字符串里不支持 ${}。当然,如果你要使用 java 的方式,用 + 来拼接也可以。

3. 执行 java 等命令

在批处理脚本中直接写要运行的命令,终端就会自动去执行,但在 gradle 脚本中,如果也需要执行一些命令行下的指令时,就需要借助 Gradle 提供给我们接口。

3.1 “xxx".execute()

命令"xxx".execute()

解释: "xxx" 就是需要执行的命令,比如 svn --versiongit --versionjava -versioncmd dir 等等,直接将需要执行的命令用字符串表示后调用 .execute() 方法,这个命令就可以执行了。

切记: 虽然这种方式很简单,但也很有多问题:

  • 首先第一个,你要执行的这条命令必须在你电脑里配置了相关的环境变量,否则会报系统找不到指令的错误。
  • 第二点,这种方式下,有时看不到输出的信息,比如 svn --version 可以在控制台中看到相关信息输出,但是 java -version 这条命令却在控制台中看不到,至于为什么,还没搞懂,有清楚的还望指点一下。

示例

  • 电脑配置了相关的环境变量,控制台可以看到相关信息

println "svn --version".execute().text.trim()

解释:text.trim() 是可以获取到命令执行之后的输出结果,所以可以直接将命令的执行结果打印出来查看命令的执行情况,如果需要这方面的需求的话,不然只需 "svn --version".execute() 命令就会执行了。

  • 电脑配置了相关的环境变量,但控制台却看不到相关输出信息

println "java -version".execute().text.trim()

解释:这点我也搞清楚,不懂为什么通过 text 就可以获取到 svn 命令的执行结果,但就获取不到 java 命令的执行结果。但,虽然控制台看不到信息,命令还是有成功执行的,我们可以测试一下:

groovy def workDir = "C:\\users\\suxq\\desktop" "javac -d . A.java".execute([], new File(workDir))

解释:我在桌面放一个 A.java 文件,而通过 javac -d . A.java 命令可以在当前路径下生成一个 A.calss 文件。所以,通过 "xxx".execute() 方式确实可以正确执行指定命令,但有时可能在控制台看不到输出信息,至于原因我不清楚。

另外,execute() 这个方法可以接收两个参数,第一个参数我也不清楚,第二个参数是可以指定命令执行的工作路径,因为我把 A.java 放在桌面,所以我需要指定这条命令的工作路径是在桌面,不然的话,这条命令中的 A.java 就需要给出绝对路径。

  • 电脑没有配置相关环境变量,脚本执行报错

"git --version".execute()

解释:我电脑没有配置 git 的环境变量,因此,通过这种方式来执行命令的时候是会报错的。

3.2 task xxx(type: Exec) {}

命令task xxx(type: Exec) {}

解释:这种方式是官方给的教程里介绍的方式,官方链接跳转

示例

task sign4(type:Exec) {
    group = sign

    //设置工作路径
    workingDir ‘C:\\Users\\suxq\\Desktop‘

    //执行 dir命令, /c 表示 cmd窗口执行完 dir 命令后立即关掉,至于 cmd 后可带哪些参数,可在终端下 cmd /? 查看
    commandLine ‘cmd‘, ‘/c‘, ‘dir‘  

    //执行 java -version 命令
    //commandLine ‘java‘, ‘-version‘

    //执行 svn --version 命令
    //commandLine ‘svn‘, ‘--version‘

    //执行 adb devices 命令
    //commandLine ‘cmd‘, ‘/c‘, ‘adb devices‘
}

解释:通过 Gradle 提供好的类型为 Exec 的 task,然后通过配置工作路径 workingDir, 需要执行的命令 commandLine,一个 Gradle 脚本就好了,然后通过 android studio 提供的 ui 界面执行或者 Gradle 的命令行形式直接执行这个 task 即可。

稍微介绍下上述一句话带过的 Gradle 脚本执行方式:

Android Studio方式

  1. 新建 Gradle 脚本文件,如 sign.gradle,放在与你项目的 app 层级的 build.gradle 同级别即可
  2. 在 app 层级的 build.gradle 文件开头添加:apply from: ‘sign.gradle‘
  3. 在你自己建的 gradle 脚本文件中编写你的脚本代码,注意你自定义的 task 最好指定一个 group
  4. 此时在 Android Studio 右侧的 Gradle 面板中就可以找到你自行指定的 group 中的所有 task,点击即可执行

如果你的 Gradle 脚本文件中的 task 不指定一个 group 的话,那么在 Gradle 面板中就有的你找了

gradle 命令行方式

如果你电脑有配置好 Gradle 的环境变量,那么你直接在终端中输入命令:gradlew task名 即可,如上图中有 sign, sign2 等四个 task,终端下输入 gradlew sign2 就可以执行 sign2 的工作了。

如果电脑没配置 Gradle 环境变量,那每个项目下都会有一个 Gradle 文件夹,它支持我们执行命令,所以你也可以在 Android Studio 的 Terminal 中直接执行命令即可,打开它的时候路径默认为项目根目录的路径,在这里就可以执行 Gradle 的命令了。

3.3 exec {}

命令exec {}

解释:这个命令的用法可以说跟 3.2 介绍的方式一模一样,我个人针对这两个的区别理解就是,3.2 介绍的方式必须通过 task 方式去执行一个命令,但 exec{} 的方式可以通过方法也可以通过 task 方式,比较灵活,这是我的理解。

示例

def sign() {
    //设置命令执行结果的输出的地方
    def out = new ByteArrayOutputStream()
    //通过 exec {} 方式来执行命令
    exec {
        workingDir ‘C:\\users\\suxq\\desktop‘
        commandLine ‘cmd‘, ‘/c‘, ‘dir‘
        //修改命令输出的地方,默认为控制台
        standardOutput = out
    }
    //将命令的执行结果作为方法的返回值
    return out
}

解释:def sign() 定义了一个方法,内部就可以通过 exec{} 来执行指定的命令,并且可以通过修改命令结果输出的地方来达到获取命令执行的结果的目的。而且,这个方法可以在你的 Gradle 脚本中在你需要的地方调用即可,而通常 task 之间只有前后依赖关系,而没有内部嵌套调用关系。

4. 完整示例

学习完上述内容后,知道了如何遍历操作,如何处理字符串,如何通过 Gradle 执行命令,就差不多可以来写 Gradle 脚本,让它帮我们做些事了,还是跟上一篇相同的场景:

场景:遍历指定路径目录下的所有 apk 文件,并通过一个 sign.jar 文件,分别对每个 apk 文件执行 java 命令来进行签名工作,sign.jar 接收两个参数,一个是需要签名的 apk,另外一个为输出的 apk,要求签名后的 apk 命名方式为将原文件名中的 unsign 替换成 google,并输出在跟 apk 同一个目录内即可。

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

Gradle 脚本

task sign {
    group = sign

    doLast {
        def signJar = "c:\\users\\suxq\\desktop\\sign.jar"
        def apkPath = ‘c:\\users\\suxq\\desktop\\outputs\\‘

        fileTree(file(apkPath)){
            include "*.apk"
        }
        .each {file ->
            def outApk = file.name.replace("unsign", "google")
            //由于场景是模拟的,因此这里就只是将最后执行的java命令输出,从输出的命令中就可以看出命令是否可以正确执行
            def java = "java -jar ${signJar} ${file.name} ${outApk}"
            println java

            //实际场景下,执行这句代码,上面代码只是为了看整合之后的命令
            //"java -jar ${signJar} ${file.name} ${outApk}".execute()
        }
    }
}

效果:完美,可以解放双手,让脚本干活去吧~



最近(2018-03)刚开通了公众号,想激励自己坚持写作下去,初期主要分享原创的Android或Android-Tv方面的小知识,准备可能还有点不足,感兴趣的可以先点一波关注,谢谢支持~~

原文地址:https://www.cnblogs.com/dasusu/p/9064481.html

时间: 2024-08-29 13:30:36

写完批处理脚本,再写个Gradle脚本,解放双手的相关文章

写个批处理脚本来帮忙干活--遍历文件夹&字符串处理

这次打算写几篇关于脚本方面的博客,主要是记录一下 Gradle 脚本和批处理脚本的一些写法,方便后续查阅. 前言 平常开发过程中,一些较为重复的手工性工作,如果能让脚本来帮忙处理,自然是最好的,刚好之前有些工作有点过于重复且都是手工性去完成,所以就想着能否写个脚本来处理. 因为我还是用的 windows 开发,所以最开始想到的就是批处理脚本,但写完后发现,重复性工作是可以交给脚本去处理了,但每次要执行这个脚本文件还得打开脚本所在的文件夹找到脚本点击去执行. emmm,因为我是开发 Android

写完代码再写诗,是多么陶醉~

文/向右奔跑(简书作者) 原文链接:http://www.jianshu.com/p/25e07f8095a8 著作权归作者所有,转载请联系作者获得授权,并标注"简书作者". 两周前,我发起一个活动,让大家从现在开始每天记录学习的内容,可以是学习的感受感言,也可以整理学习笔记.知识点.要求就是每天都写,每天去记录. 每天坚持记录.总结,是一件不容易的事情.我以自己坚持跑步和早起为例,告诉大家怎样从一件小事开始持续坚持.也分享几篇文章,如<为什么你应该(从现在开始)写博客>等

在require回调函数中执行tooltipvalidator.init不需要另外再写逻辑

尽管每个人学习开发的过程会不一样,然而无论如何,系统的学习方法对每个学习者来说都是至关重要的.对于初学者,应该经常向资深的游戏开发者学习,通过他们的直播和视频,学习游戏开发的技巧.你从这些专家们身上学到的东西越多,你就可以越快成为优秀的开发者. 通过proceed()方法可以调用目标对象的相应方法,从而实现对目标方法的完全控制! angular2 的依赖注入包含了太多的内容,其中的一个重点就是注入器,而注入器又非常难理解,今天我们不深入介绍注入器的内容,可以参考官方文档,我们今天来说注入器的层级

论文写完啦

已经自信到有点自大了,觉得自己的论文简直就是巨作,很完美.这次写论文我深刻体会到了完美的定义,不是天衣无缝,而是你竭尽所能的做到了最好.对我来说,我的论文就已经是完美了.可是,为什么都没人想看我的论文呢.我密了好几个人想不想看我的论文,都没回应.于是我专门改了QQ签名档.但我想还是没人会真的想看吧. 我太兴奋啦.看了下论文的word,创建日期是6/25,但我想再之前应该还是有一些草稿,不然20多天就从零到写完,也太厉害了.这期间,改了起码有三个版本.真的是天翻地覆的变化.其中又以这个礼拜的变化最

script脚本中写不写$(document).ready(function() {});的区别

$(document).ready() 里的代码是在页面内容都加载完才执行的,如果把代码直接写到script标签里,当页面加载完这个script标签就会执行里边的代码了,此时如果你标签里执行的代码调用了当前还没加载过来的代码或者dom,那么就会报错,当然如果你把script标签放到页面最后面那么就没问题了,此时和ready效果一样. $(document).ready(function(){})可以简写成$(function(){}); 点击段落后,此段落隐藏: <html> <head

linux下安装codeblocks及写完程序之后编译成功但无法运行的原因

一:在软件中心输入codeblocks,然后点击安装,等着装完就行了. 再按ctrl+alt+t 打开终端 输入 sudo apt-get install gcc 而后再输入sudo apt-get install g++ 最后打开codeblocks写个 helloworld 试试吧. 二:helloworld小程序写完后,也编译通过了,但是却无法运行,那么你再看看保存的地方吧,要是不是保存在linux下的文档了,而是保存在磁盘里的话就是造成不能运行的结果了,更改保存位置试试看呗. 以上仅是我

不写完不让回家的JQuery的事件与动画

在这看不见太阳的小黑屋里,苦逼的一天又开始了 好了闲话我也就不扯了,接下来我就来说说我对jQuery事件和动画的理解吧!!! 还是得再扯两句,我们敬爱的,Y老师讲完了,jQuery事件和动画,对着我们这听得一脸懵逼的人,说了一句不写完就别回家,心里咯噔一下,比被车撞都...... 一.jQuery中事件 1.如何加载DOM呢? 在常规的JavaScript代码中,我们通常使用window.onload方法对吧,而在jQuery中,使用的是$(document).ready()方法.$(docum

用putty玩linux的时候由于以前用window 习惯写完东西按一下ctrl+s 保存

问题描述:用putty玩linux的时候由于以前用window 习惯写完东西按一下ctrl+s 保存,但是在putty一按下就不能再输入了.后来查找到:ctrl+s 是putty的一个命令大概是这样子:”Long long ago“ 某些旧的”哑终端“会在发送过来的数据太多,显示速度跟不上时发送一个Ctrl+s让对方等一下,然后再准备好继续显示时发送一个Ctrl+q.Putty“兼容”了这个特性.也有人说是Ctrl+s是锁定屏幕用的 .不管是怎样,当你不小心在Putty中按了Ctrl+s后再按一

IP的计算------HDOJ杭电2206(写完脑洞大开,想象力要足够丰富)

Problem Description 在网络课程上,我学到了很多有关IP的知识.IP全称叫网际协议,有时我们又用IP来指代我们的IP网络地址,现在IPV4下用一个32位无符号整数来表示,一般用点分方式来显示,点将IP地址分成4个部分,每个部分为8位,表示成一个无符号整数(因此不需要用正号出现),如192.168.100.16,是我们非常熟悉的IP地址,一个IP地址串中没有空格出现(因为要表示成一个32数字). 但是粗心的我,常常将IP地址写错,现在需要你用程序来判断. Input 输入有多个c