#! /bin/sh -
cd /PHOTAN || exit
fn=$(ls -t | tail -n -30)
mv -f -- "${fn}" /old
所有我想要的东西都是保留最近的30个文件...但是无法通过mv "文件名太长"问题
请帮助'
答案 0 :(得分: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
命令用换行符替换空字节(但这样做会丢失文件名边界的标识)。
代码甚至可以使用包含换行符的文件名,但仅适用于sed
和sort
支持(非标准)-z
选项来处理以null结尾的输入行的系统' - 这意味着使用GNU sed
和sort
的系统(即使是Mac OS X上找到的BSD sed
也没有,尽管Mac OS X sort
是GNU {{1并支持sort
)。
唉! shell设计用于在文件名之间而不是文件名之间显示空格。
正如BroSlow中comment所述,如果你假设'文件名中没有新行',那么代码可以更简单,更便于携带 - 但它仍然很棘手:
-z
需要ls -t |
tail -30 |
{
list=()
while IFS='' read -r file
do list+=( "$file" )
done
mv -f -- "${list[@]}" /old
}
,以便保留文件名中的前导和尾随空格(以及制表符)。
我顺便注意到Korn shell不需要括号,但Bash会这样做。