当目录数超过10时,我想删除目录中的旧目录。 当我运行命令时,
sudo rm -r `ls -1t /ebs/lucene_indexes/ | tail -n +10`
我收到以下错误:
rm: cannot remove â1432120954â: No such file or directory
rm: cannot remove â1432120945â: No such file or directory
rm: cannot remove â1432120937â: No such file or directory
rm: cannot remove â1432120927â: No such file or directory
rm: cannot remove â1432120917â: No such file or directory
rm: cannot remove â1432118817â: No such file or directory
rm: cannot remove â1432118631â: No such file or directory
rm: cannot remove â1432118349â: No such file or directory
但是当我执行时:
ls -1t /ebs/lucene_indexes/ | tail -n +10
我得到以下输出:
1432120954
1432120945
1432120937
1432120927
1432120917
1432118817
1432118631
1432118349
出于某种原因,当我执行第一个命令时,目录名称会被追加并由特殊字符添加前缀。所以它失败了。为什么会这样?这里出了什么问题?
答案 0 :(得分:4)
我怀疑您执行/ebs/lucene_indexes/
时不在ls
目录中,这意味着列出的目录不在您当前的工作目录下。我会cd
进入目录并从“。”执行ls
。我不记得有任何简单的方法让find
按时间排序,
(cd /ebs/lucene_indexes/; sudo rm -r $(ls -t | tail -n +10 ))
得到你想要的东西?请注意,周围的括号在子shell中执行cd
,因此现有的cwd
不会更改。此外,管道中不需要-1
。
答案 1 :(得分:2)
xargs
是你的朋友,例如:
ls -1t /ebs/lucene_indexes/ | tail -n +10 | xargs rm -r
干杯,
答案 2 :(得分:1)
mpez0's answer包含关键指针:rm
命令不一定在/ebs/lucene_indexes/
中运行,因此,当从其他目录运行时,它会使用ls -1t
生成的仅文件名输出失败。
mpez0的答案解决了这个问题,但是,就像OP的命令一样,它打破了带有嵌入空格的文件名;这是正确处理带有嵌入空格的文件名的版本:
(cd /ebs/lucene_indexes/ && \ls -t | tail -10 | sudo xargs -I {} rm -r -- {})
它使用xargs
来读取ls
的输出行,并为每个输出行rm
调用-I
,每行作为单行命令行参数;这个符合POSIX标准的xargs
用法的缺点是你得到多个 rm
个调用。
使用GNU xargs
能够使用-0
选项解析NUL分隔的输入,通过xargs
传递,您可以提高命令效率尽可能多的参数适合命令行,导致(通常)仅一次调用rm
:
(cd /ebs/lucene_indexes/ && \ls -t | tail -10 | tr '\n' '\0' | sudo xargs -0 rm -r --)
tr '\n' '\0'
用NUL(0x0
)替换换行符,准备按xargs -0
进行处理。xargs -0 rm -r --
将所有NUL分隔的标记从stdin传递为命令行参数到rm -r
,从而导致(通常)仅一个调用rm
的
tr '\n' '\0'
/ xargs -0
组合,只有xargs rm -r
,带有嵌入空格的路径会被错误地分解为多个参数,从而导致rm
失败注意ls
的配置方式(--color
行为,绕过名为ls
的潜在别名\ls
),如评论中所述,也值得,但这让我们得到了更大的一点:它是generally not a good idea to parse ls
output,因为通常有更好更强大的替代方案(globbing,find
)。
不幸的是,在这种情况下避免ls
会严重地使命令复杂化。继续阅读基于find
的解决方案。
注意:在一天结束时,这个基于find
的解决方案与基于ls
的解决方案相比没有太大的优势,因为它也不适用于带有嵌入换行符的文件名;然而,会帮助处理包含标签字符(\t
)等异域字符的文件名,ls
通常在输出中表示为?
。
find /ebs/lucene_indexes -mindepth 1 -maxdepth 1 -printf '%T@\t%p\n' |
sort -n | head -10 | cut -f2- | tr '\n' '\0' | sudo xargs -0 rm -r --
注意:在以下说明中,“file”指的是文件和目录。
find /ebs/lucene_indexes -mindepth 1 -maxdepth 1
相当于ls /ebs/lucene_indexes
,但它返回路径,而不仅仅是文件名(并且输出不会被排序)。-printf '%T@\t%p\n'
在纪元时间(%T@
)输出每个文件的最后修改日期,然后是标签,后跟文件的完整路径(%p
)。sort -n
然后对输出进行排序,以便首先列出最旧的文件,然后head -10
输出最旧的10个文件。cut -f2-
从输出中删除日期列,只留下完整路径。tr '\n' '\0'
和xargs -0 rm -r --
按上述方式工作。