如何将最近的10个文件从一个目录复制到另一个目录?

15

所有我的html文件都存放在这里:

/home/thinkcode/myfiles/html/

我想把最新的10个文件移动到/home/thinkcode/Test

目前我有以下代码,请纠正我。我正在寻找一行代码解决!

ls -lt *.htm | head -10 | awk '{print "cp "$1" "..\Test\$1}' | sh

3
你可以使用xargs来避免使用awksh(感觉很丑),或者可能使用find ... -exec来运行一个命令。 - KurzedMetal
我可以使用find命令完成,但是我想知道如何使用awk完成相同的操作! - ThinkCode
3
请参阅 BashFAQ/003BashFAQ/099 - Dennis Williamson
4个回答

11
ls -lt *.htm | head -10 | awk '{print "cp " $9 " ../Test/"$9}' | sh

6
ls 在列出文件名中存在特殊字符时常常表现不佳。另外,解析 ls -l 命令的输出存在危险性。最好编写一个小的 Perl 脚本,对所有文件进行统计并按日期排序。如果一定要使用 ls 命令,至少不要包含 -l 参数... ls -t *.html | head -10 同样有效。 - Barton Chittenden
结尾的|sh是必要的吗? - neverMind9
当文件名中含有空格时,此命令无法正常工作。请使用ls -t *.htm |head -10 |awk '{print "cp -- \"" $0 "\" ../Test/"}' |sh`代替。 - aleck099
你能解释一下你的代码是做什么的吗? - CDuvert

8

cp 似乎能够理解反引号命令。因此,您可以使用像这样的命令将最新的10个文件复制到另一个文件夹中,例如 /test:

cp `ls -t *.htm | head -10` /test

这正是我想要的。 - OGHaza
2
工作得很好,直到您的文件名中有空格,或者更糟糕的是,在您的文件夹中有一个名为; rm -fr --no-preserve-root / ; .htm的文件。 - localhost

7

这是一个不使用ls命令的版本。它应该对文件名中的奇怪字符更加安全:

find . -maxdepth 1 -type f -name '*.html' -print0 
     \| xargs -0 stat --printf "%Y\t%n\n" 
     \| sort -n 
     \| tail  -n 10 
     \| cut -f 2 
     \| xargs cp -t ../Test/

我使用find有以下几个原因:

1)如果一个目录中有太多文件,bash在通配符扩展*时会出现错误。

2)使用-print0参数来调用find可以解决bash将文件名中的空格扩展为多个标记的问题。

* 实际上,bash共享其通配符扩展和环境变量的内存缓冲区,因此这并不完全是文件名数量的函数,而是文件名和环境变量的总长度。太多的环境变量 => 无法进行通配符扩展。

编辑:合并了@glennjackman的一些改进。保留了最初使用find以避免在大型目录中使用可能失败的通配符扩展。


3
不使用ls可以加1分。可以更简单一些:stat -c "%Y\t%n" *.html | sort -n | tail -10 | cut -d " " -f 2- | xargs cp -t ../Test。该命令的作用是将当前目录中最后修改时间最新的10个.html文件复制到../Test目录中。 - glenn jackman
@glennjackman: 这个cut是在tab字符处吗?当你粘贴时,它会打印为“ ”吗? - ToolmakerSteve
实际上,制表符是cut命令的默认分隔符,所以你可以完全省略-d参数。 - Barton Chittenden
当通配符扩展失败时,这个解决方案确实非常有用。使用cp -u -t(注意标志的顺序)仅在源文件新于目标文件或目标文件丢失时才进行复制。 - CDuvert

5
ls -lt *.html | head -10 | awk '{print $NF}' | xargs -i cp {} DestDir

在上面的例子中,DestDir是复制的目标目录。
在xargs后面添加-t以查看执行命令。即xargs -i -t cp {} DestDir
有关更多信息,请查看xargs命令编辑:如@DennisWilliamson所指出的(并且也检查了当前的man页面)关于-i选项此选项已过时;请改用-I。
此外,这两个解决方案都依赖于所涉及的文件名不包含任何空格或制表符。

如何将文件复制到../test目录? - ThinkCode
ls -lt *.htm | head -10 | awk '{print $NF}' | xargs cp * ../Test/?不起作用。如何从管道中收集文件名并将其提供给复制命令? - ThinkCode
更新了我的答案以回答您的问题。 - Levon
@Levon,我是在评论ThinkCode的评论。他执行了cp *命令。 - J-16 SDiZ
2
如果文件名包含空格或制表符,则print $NFprint $9都会失败。 xargs -i已被弃用 - 请改用xargs -I {} - Dennis Williamson
@DennisWilliamson 有用的信息,我已经注意到了。我会更新我的答案,谢谢! - Levon

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接