我编写了一个脚本,用于根据月份列出文件,用户读取该文件的方式如下:-
echo "Enter Month"
read month
ls -al | awk '$6 == "$month" {print}'
我给用户输入的是 Aug,但我没有得到任何结果。但是当我写
ls -al | awk '$6 == "Aug" {print}'
我得到了准确的结果。我做错了什么吗?请帮忙
答案1
最主要的是:变量名在单引号内不展开。这是“更好的”(即错误较少的)一行:
ls -al | awk '$6 == "'"$month"'" {print}'
# this is in single quotes ^^^^^^^ ^^^^^^^^^
但:
- 但在某些地区这仍可能会失败。
LC_ALL=C
预先设定或许如此。 - 使用 ,
$month
你可以将(几乎?)任何东西注入awk
。有更好的方法在 中使用变量awk
;-v
选项应该更安全(感谢user000001指出这一点)。 - 你不应该解析输出
ls
首先。
正确的解决方案可能是使用find
和stat
。以下代码可能不是最快的解决方案,但它更强大,因为:
- 丢弃
$month
与预定义值不匹配的值, - 使用
find
而不是解析ls
。
代码:
#!/bin/sh
echo "Enter Month"
read month
case "$month" in
1|01|Jan|jan|January|january) monthN=01;;
2|02|Feb|feb|February|february) monthN=02;;
# ...
10|Oct|oct|October|october) monthN=10;;
# ...
*) echo Error! >&2; exit 1;;
esac
find ./ -maxdepth 1 -exec sh -c '[ `stat -c %y "$1" | cut -c 6-7` = "$2" ]' sh {} "$monthN" \; -ls
我在 Debian 上测试过;它可能不是超级可移植的。但它展示了一般的方法。
最后一行针对当前目录中的每个对象(包括./
其自身)调用一个单独的 shell。此 shell 用于stat
获取 mtime 信息,然后cut
从中提取两位数的月份数。[ ... ]
将结果与所选月份数进行比较。如果此测试成功,则对对象find
执行其自身的测试(您可以使用或代替)。ls
-print
-print0
请注意,这永远不会返回../
。另一方面,find
允许您使用其他测试(如-type f
),因此这种方法非常灵活。