Linux中的“for”构造在ksh中

时间:2010-08-01 20:46:46

标签: ksh

我通常在ksh中使用for构造来快速迭代文件列表以对其执行某些操作。它在这种情况下似乎不起作用:

The file info looks like: 
$ ls -l tmp.*  
rw------- 1 op general 375 Jul 25 04:09 tmp.zzyhsg4  
...  
so on. Basically a lot of tmp.* files.    

Now when I try  
$ ls -lS | grep 'Jul 25' | grep 'tmp.*' | cut -d' ' -f9 | more  
tmp.zzyhsg4  
..  

它将按预期打印文件名。 但是当我尝试下面的

$ for i in `ls -lS | grep 'Jul 25' | grep 'tmp.*' | cut -d' ' -f9`
>do  
>echo $i  
>done  

这不会打印以tmp。*开头的所有文件的名称,这些文件是在7月25日按大小排序的。它打印尺寸列。有趣的是,如果我用f6替换f10进行切割,它将正确打印月份列。它在f9之后开始破裂。

有什么想法吗?

2 个答案:

答案 0 :(得分:1)

要获取名为tmp.*的所有文件,请使用

$ ls -lS tmp.*

通过剪切,您可以将空间作为分隔符。这将无法正常工作。字段之间的空格数是灵活的,因此您将拥有不同数量的字段。 (每2个空格之间就有一个空字段)

更好地使用find,它可以将您的文件列表整形为您喜欢的任何形式:

$ find tmp.* -printf "%s %CD %f\\n" | grep "07/25/10" | sort -n

man find也可以在find命令中获取日期过滤)

答案 1 :(得分:1)

我无法准确再现您所描述的内容,但我有一些建议可以编写更可靠的命令。

cut -d' '按空格分隔字段。如果连续有两个空格,则它们之间有一个空字段。因此,如果您尝试使用Aug 1而不是Jul 25,则文件名列会移动1.如果您尝试使用超过6个月的文件,则会替换(5个字符)时间按一个空格,然后是4位数年份。此外,根据您的ls版本,某些列之间可能有多个空格。另一个问题是某些版本的ls不会显示group列。然后一些文件名包含空格。某些文件名包含ls可能显示为?的特殊字符。总之,您无法通过计算空格来解析ls -l的输出,甚至无法通过计算以空格分隔的字段来解析ls -l的输出。只是不解析ls的输出

用于生成现有文件名称列表的标准命令是find。既然你提到Linux,我会提到与GNU find(你在Linux上获得的版本)有关的选项,但不会提到其他unix。

让我们开始简单:列出当前目录中名为tmp.*的文件。

find . -name 'tmp.*'

我们只想要在7月25日创建的文件,即7天前创建的文件。

find . -name 'tmp.*' -daystart -mtime 7

这很脆弱,因为它明天不起作用。指定精确日期的通常方法是创建最早和最晚允许时间的文件,并告诉find仅返回这两者之间的日期文件。

touch -t 201007250000 .earliest
touch -t 201007260000 .latest
find . -name 'tmp.*' -newer .earliest \! -newer .latest
rm .earliest .latest

find命令以递归方式探索子目录。如果你不想要这个:

find . -name 'tmp.*' -daystart -mindepth 1 -maxdepth 1 -mtime 7

如果您希望按大小排序文件:

find . -name 'tmp.*' -daystart -mtime 7 -printf '%s\t%p\n' | sort -n -k 1 | cut -f 2-

最后,如果您要对文件进行操作,从不在反引号中使用find,使用ls的方式,因为如果文件名包含,则会失败空格或一些特殊字符,因为shell在空格中分割`command`的输出,然后对结果字进行通配。相反,请使用-exec选项find; ;版本对每个文件执行mycommand一次,{}替换为文件名,而+版本通常仅使用mycommand调用{}一次}替换为文件名列表。

find . -name 'tmp.*' -daystart -mtime 7 -exec mycommand -myoption {} \;
find . -name 'tmp.*' -daystart -mtime 7 -exec mycommand -myoption {} +