“文件名太长”bash mv命令旧文件

时间:2014-09-06 03:26:03

标签: bash shell unix mv

#! /bin/sh -
cd /PHOTAN || exit
fn=$(ls -t | tail -n -30)
mv -f -- "${fn}" /old

所有我想要的东西都是保留最近的30个文件...但是无法通过mv "文件名太长"问题

请帮助'

1 个答案:

答案 0 :(得分:2)

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

mv -f -- ${fn} /old

如果你的文件名中包含空格,那么从解析ls命令的输出开始就会遇到问题。

  

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

然后,正如我所说,你遇到了重大问题,首先是解析ls的输出问题。

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

两个带有空格的漂亮文件名。他们引起了快乐的地狱。我打算假设你在Linux或类似的东西上。您需要使用bash数组,stat命令,printfsort -zsed -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选项来处理以null结尾的输入行的系统' - 这意味着使用GNU sedsort的系统(即使是Mac OS X上找到的BSD sed也没有,尽管Mac OS X sort是GNU {{1并支持sort)。

唉! shell设计用于在文件名之间而不是文件名之间显示空格。


正如BroSlowcomment所述,如果你假设'文件名中没有新行',那么代码可以更简单,更便于携带 - 但它仍然很棘手:

-z

需要ls -t | tail -30 | { list=() while IFS='' read -r file do list+=( "$file" ) done mv -f -- "${list[@]}" /old } ,以便保留文件名中的前导和尾随空格(以及制表符)。

我顺便注意到Korn shell不需要括号,但Bash会这样做。