在进行批量的操作,或者繁琐的操作时,可以使用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
命令时,获取到的文件名如果有空格的话将不会获取之后部分,可以对变量添加""
解决问题。 cp
mv
等命令要求文件命中同样不能有空格,也可以在脚本中对变量添加""
解决。- 刚开始写
shell
脚本时最好写一句测试一句,要严谨不能想当然。