问:在Linux下怎么一次性删除掉那些修改时间为指定日期的所有文件?
答:脚本del_files_of_date.sh
用法:./del_files_of_date.sh <YYYY-mm-dd> <files...>
比如:./del_files_of_date.sh 2011-09-01 html/*.html
#!/bin/sh : ${2?"usage: $0 <YYYY-mm-dd> <files...>"} for f in "${@:2}" do modify_time=$(stat --printf '%y' "$f") if [[ $modify_time == $1* ]]; then echo "$f" "$modify_time" rm -v -- "$f" fi done
下面是此脚本的一次执行示例
[root@jfht contents]# ./del_files_of_date.sh 2011-08-01 html/*.html
html/0041bb66458751c989fe55d8dd837458.html 2011-08-01 08:55:58.000000000 +0800
已删除“html/0041bb66458751c989fe55d8dd837458.html”
html/05602e464e720e482fe0a33ac71198ea.html 2011-08-01 12:55:33.000000000 +0800
已删除“html/05602e464e720e482fe0a33ac71198ea.html”
……
……
html/ff4dd248f7f6b97bc07519d561d47111.html 2011-08-01 18:55:37.000000000 +0800
已删除“html/ff4dd248f7f6b97bc07519d561d47111.html”
[root@jfht contents]#
下面详细解释此脚本
第3行:: ${2?"usage: $0 <YYYY-mm-dd> <files...>"}
内建命令:(冒号),用来做参数扩展。如果没有,那么就会把后面${2...}的结果当做命令来执行。
No effect; the command does nothing beyond expanding arguments and performing any specified redirec-
tions. A zero exit code is returned.
[root@jfht contents]# touch 1.txt
[root@jfht contents]# ./del_files_of_date.sh 2011-09-01 1.txt
./del_files_of_date.sh: line 3: 1.txt: command not found
上面这行是没有在前面增加:命令的执行效果。
1.txt 2011-09-01 19:56:46.000000000 +0800
[root@jfht contents]#
(关于:命令的更多信息,参见“我使用过的Linux命令之:(冒号) - 啥也不做(除了……) ”)
第3行:: ${2?"usage: $0 <YYYY-mm-dd> <files...>"}
${VAR?STRING}的作用是判断变量VAR是否为空,如果为空则打印STRING指定的信息后退出。
这很适合用来检查是否提供了足够多的命令行参数或者变量是否设置,如果为否,打印使用帮助退出。
其中,?前的2,表示是第二个命令行参数。即第二个命令行参数没有设置,就打印帮助信息退出。
[root@jfht contents]# ./del_files_of_date.sh
./del_files_of_date.sh: line 3: 2: usage: ./del_files_of_date.sh <YYYY-mm-dd> <files...>
[root@jfht contents]# ./del_files_of_date.sh 2011-09-01
./del_files_of_date.sh: line 3: 2: usage: ./del_files_of_date.sh <YYYY-mm-dd> <files...>
[root@jfht contents]#
第5行:for f in ${@:2}
在Bash中for结构的写法
for VAR in LIST
do
DO_SOMETHING_OF_VAR
done
(关于 for 语句的更多信息,参见“我使用过的Linux命令之for - Bash中的For循环 ”)
第5行:for f in "${@:2}"
关于 ${@:2},其中 @ 是代表所有命令行参数,2表示从第二个参数开始的所有参数。
更通用的情况:${@:START:N},表示从第START个参数开始,截取N个参数。
要注意的是${@:2}必须写在双引号里面。
如果去掉双引号,将不能正确处理带有空格的文件名,如下所示:
[root@jfht contents]# ./del_files_of_date.sh 2011-09-03 'hello world.txt'
stat: 无法 stat “hello”: 没有那个文件或目录
stat: 无法 stat “world.txt”: 没有那个文件或目录
以空格分隔成文件名,显然不是期望的结果。
[root@jfht contents]#
加上双引号的处理情况:
[root@jfht contents]# ./del_files_of_date.sh 2011-09-03 'hello world.txt'
stat: 无法 stat “hello world.txt”: 没有那个文件或目录
[root@jfht contents]#
第7行:modify_time=$(stat --printf '%y' "$f")
关于 $(),把其中的内容当做命令行执行,把标准输出保存到字符串中。
也可以用一对反引号来实现,写作 modify_time=`stat --printf '%y' "$f"`
第7行:modify_time=$(stat --printf '%y' "$f")
$(stat --printf '%y' "$f") 用来输出指定文件$f的修改时间(如 2011-09-01 10:26:04.000000000 +0800)。
stat用来打印文件的相关信息的,比如大小、修改时间、访问时间等。
开始时我采用的参数是--format,后面改用--printf更好些。
use the specified FORMAT instead of the default; output a newline after each use of FORMAT
--printf=FORMAT
like --format, but interpret backslash escapes, and do not output a mandatory trailing newline. If you
want a newline, include \n in FORMAT.
The valid format sequences for files
%y Time of last modification
(关于 stat 命令的更多信息,参见“我使用过的Linux命令之stat - 显示文件或文件系统状态 ”)
第8行:if [[ $modify_time == $1* ]]; then
在Bash中 if 结构的写法 如下
if CONDITION; then
DO_SOMETHING
fi
如果 DO_SOMETHING 部分的语句很少,也可写作
if CONDITION; then DO_SOMETHING; fi
但别忘了在 fi之前加上分号,否则 Bash解析的时候不知道命令是否结束了。
(关于 if 语句的更多信息,参见“我使用过的Linux命令之if - Bash中的条件判断语句 ”)
第8行:if [[ $modify_time == $1* ]]; then
关于 [[ ]],在Bash中 [[ 是个内建命令。 与 [ ] 不同的是,可以不用双引号把变量引用起来,而且支持通配符模式的匹配。
[[ $modify_time == $1* ]] 表示modify_time是以第1个命令行参数开头。
Returns a status of 0 or 1 depending on the evaluation of the conditional
expression EXPRESSION. Expressions are composed of the same primaries used
by the `test' builtin, and may be combined using the following operators
( EXPRESSION ) Returns the value of EXPRESSION
! EXPRESSION True if EXPRESSION is false; else false
EXPR1 && EXPR2 True if both EXPR1 and EXPR2 are true; else false
EXPR1 || EXPR2 True if either EXPR1 or EXPR2 is true; else false
When the `==' and `!=' operators are used, the string to the right of the
operator is used as a pattern and pattern matching is performed. The
&& and || operators do not evaluate EXPR2 if EXPR1 is sufficient to
determine the expression's value.
第10行:rm -v -- "$f"
rm命令用于删除文件。增加 -v 参数,可以打印删除的文件信息。增加 -- 参数,是为了正确的处理 $f 以 - 开头的情况。
explain what is being done
To remove a file whose name starts with a ‘-’, for example ‘-foo’, use one of these commands:
rm -- -foo
rm ./-foo
(关于 rm 命令的更多信息,参见:“我使用过的Linux命令之rm - 删除文件或目录 ”)
本文链接:http://codingstandards.iteye.com/blog/1163913 (转载请注明出处)
PS: 第5到12行完全可以精简为一行。
脚本 del_files_at_date.sh
#!/bin/sh : ${2?"usage: $0 <YYYY-mm-dd> <files...>"} for f in "${@:2}"; do [[ $(stat --printf '%y' "$f") == $1* ]] && rm -v -- "$f"; done
[root@jfht contents]# ./del_files_at_date.sh
./del_files_at_date.sh: line 3: 2: usage: ./del_files_at_date.sh <YYYY-mm-dd> <files...>
[root@jfht contents]# touch test1.txt 'test space.txt'
[root@jfht contents]# ./del_files_at_date.sh 2011-09-02 test*.txt
已删除“test1.txt”
已删除“test space.txt”
[root@jfht contents]#