在进行批量的操作,或者繁琐的操作时,可以使用shell编写脚本来简化操作。我使用过众多别人编写的脚本,但是自己从来没有写过。今天正好碰到一个问题,不想繁琐的去挨个操作,那么就尝试着写一个脚本来方便操作一下吧。
首先说一下自己遇到的问题,今年去参加了CocoaChina开发者大会,会上的PPT很好,今天在网上把他们下载了下来,但是问题是,他们的命名很长而且前一部分都是一样的,类似于"CocoaChina2013开发者大会-……",前一部分都是重的,在Finder里看起来很是不方便,根本看不到有用的文件名信息,所以我决定要把这十多个文件重命名去掉前缀。
从来没有编写过shell脚本,向来都是使用shell命令的我,先从学习编写shell脚本文件开始吧!
在文本编辑器中第一行(必须是第一行)首先键入#!/bin/sh,符号#!用来告诉系统它后面的参数是用来执行该文件的程序。
注释
在shell中#代表注释,直到这一行结束。
变量
在shell中,变量都由字符串组成,变量名无需提前声明,写了就可以直接赋值,变量名=值(这里等号两边一定不能有空格)。
取变量时要使用$符号。有时在一长串字符串中包含变量,可以对变量名加上{}来区分。例如有一个变量num=2
echo "this is the $numnd",这样会有问题,我们要写成echo "this is the ${num}nd"。
流程控制
只写一下本次用到的for循环,其他的流程控制以后用到时在学习。
for-loop表达式查看一个字符串列表 (字符串用空格分隔) 然后将其赋给一个变量:
for var in ….; do
….
done
在下面的例子中,将分别打印ABC到屏幕上:
1 2 3 4 | |
这里参考的文章是Linux shell脚本编写基础
在我写的shell脚本中则是使用循环输出当前文件夹下文件的名字:
1 2 3 4 5 | |
接下来就是对获取到的每一个文件名的字符串进行截取,删掉不需要的部分:
1 2 3 4 5 6 7 | |
这里学习了一下shell字符串的操作知识,:选取子串 #正向截取子串 %逆向截取子串 ##正向最长匹配 %%逆向最长匹配。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | |
这里参考的文章Bash Shell字符串操作小结
最后就是将文件重命名了:
1 2 3 4 5 6 7 8 | |
运行时发现只有部分文件被成功重命名了,其余的都不成功,而这些不成功的文件名中都包含空格,空格是很大一个问题,在获取原文件名时文件名就被空格截断了,导致文件名不全。因而重命名也是失败的,找不到源文件。
参考这篇文章SHELL技巧:处理文件名中的那些空格
找到了解决方法,对变量添加""使空格被正确处理,这不是最好的方法,但是在我这个小小的脚本中完全可以了。
文章中还介绍了一种终极解决方法就是设置IFS(the Internal Field Separator),但是在设置之前先保存当前的IFS,操作完成之后在设置回去。
1 2 3 4 5 6 7 | |
但是我这样使用之后经过测试发现,并不能解决问题,文件名被读取成其他怪异的形式了,空格是被正常读取了但是-也被读取成空格了,我不知道这是为什么,有知道的欢迎告诉我。
最后附上自己写的完整的shell脚本,虽然很短,但这是第一次写,也算是个入门吧。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | |
总结一下需要注意的地方
- 在写
shell脚本时不能延续写其他代码乱加空格的习惯,空格在shell中很重要,随便加空格会导致shell脚本执行失败。 - 还是空格问题,使用
basename命令时,获取到的文件名如果有空格的话将不会获取之后部分,可以对变量添加""解决问题。 cpmv等命令要求文件命中同样不能有空格,也可以在脚本中对变量添加""解决。- 刚开始写
shell脚本时最好写一句测试一句,要严谨不能想当然。