2014-09-06 99 views

回答

2

符号"${fn}"将所有文件名添加到单个参数字符串中,并用空格分隔。只是这一次,假设你不必担心带空格的文件名,你需要:

mv -f -- ${fn} /old 

如果您有空格的文件名,开始解析,然后你有问题输出ls命令。

但是,如果您不必担心文件名中的空格?

然后,正如我所说,你有大问题,从解析ls的输出问题开始。

$ echo > 'a b' 
$ echo > ' c d ' 
$ 

两个漂亮的文件名,其中包含空格。他们造成快乐的地狱。我即将假设你在Linux上或类似的东西。您需要使用bash阵列,stat命令,printf,sort -z,sed -z。或者你应该简单地用空格来限制文件名;它可能更容易。

names=(*) 

阵列names包含每个文件名作为一个单独的数组元素,前缘和后缘和嵌入的空格都正确处理。

names=(*) 
for file in "${names[@]}" 
do printf "%s\0" "$(stat -c '%Y' "$file") $file" 
done | 
sort -nzr | 
sed -nze '1,30s/^[0-9][0-9]* //p' | 
tr '\0' '\n' 

for环分别评估每个文件的修改时间,和结合了修改时间,空间,和文件名成一个字符串后跟一个空字节来标记串的结束。 sort命令以数字方式对'行'进行排序,假设由于-z选项导致行由空字节终止,并且最先放置最近的文件名。 sed命令仅打印前30个'行'(文件名); tr命令用空行替换空字节(但这样做会丢失文件名边界的标识)。

代码工作甚至用含有换行符的文件名,但只能在系统中sedsort支持(非标准)-z选项处理空终止输入“线” - 这意味着使用GNU sedsort系统(即使在Mac OS X上找到的BSD sed也没有,尽管Mac OS X sort是GNU sort并确实支持-z)。

呃!该shell是为空间出现在文件名之间而不是文件名而设计的。


作为一个comment注意到BroSlow,如果你假设,那么代码可以更简单,更接近便携“在文件名中没有新行” - 但它仍然是棘手:

ls -t | 
tail -30 | 
{ 
list=() 
while IFS='' read -r file 
do list+=("$file") 
done 
mv -f -- "${list[@]}" /old 
} 

的需要使用IFS='',以便保留文件名中的前导空格和尾随空格(以及制表符)。

我注意到Korn shell不需要大括号,但Bash可以。

+0

但是,如果您不必担心文件名中的空格? – Gabe 2014-09-06 03:37:26

+0

然后你有重大问题!让我冥想吧;这是非常不愉快的,无论如何。你在Linux或其他类Unix平台上吗? – 2014-09-06 03:39:16

+0

可以假定没有带有换行符的文件并解析'ls'输出。但为了完整性+1。 – BroSlow 2014-09-06 08:35:10