如何复制文件夹中的所有文件(不包括正在写入的文件)?


12

downloading通过HTTPie将多个文件下载到一个文件夹中。一个bash脚本旨在处理下载的文件,我尝试将下载的文件复制到另一个文件夹

find /folder/downloading -type f -exec mv '{}' /folder/downloaded \;

但这还会复制尚未完成的文件。我试图通过添加-mmin +5到命令来限制传输到较旧的文件。什么是有效的命令以使文件被写入而仅传输下载的文件?


如果复制到同一文件系统,并且您将下载程序设置为不重命名(先下载%.part然后重命名为%)。然后,如果下载程序运行良好(没有其他奇怪的事情),那么您应该能够重命名(mv)文件。
ctrl-alt-delor

1
您要进行哪种处理?最有可能使用更简单的选项,例如使用管道。
Gardenhead '17

Answers:


11

效率不高,但是您可以执行以下操作:

find /folder/downloading -type f -exec sh -c '
  for file do
    lsof -F a "$file" | grep -q w || mv "$file" /folder/downloaded
  done' sh {} +

即检查该文件不与列出w仪式a在CCESS模式ls的吨of尔斯之前mÒ v荷兰国际集团。

通常在基于Linux的操作系统上可以找到的psmisc实现fuser具有-w功能(检查打开的文件是否可以写入),但不幸的是,该实现只能-k杀死相应的进程。但是,看来您仍然可以使用不执行任何操作的伪信号0来使用它:

find /folder/downloading -type f -exec sh -c '
  for file do
    fuser -s -w -k -0 "$file"  || mv "$file" /folder/downloaded
  done' sh {} +

如果要查看阻止移动的过程,-s请将其删除(甚至将其替换-v为)。

请注意,如果您不是以超级用户身份运行这些命令,则只会获得有关进程的信息。如果下载文件的进程正在以其他用户身份运行,则将不会检测到它们。

还要注意,除非将文件移动到其他文件系统,否则移动文件不会阻止当前正在写入文件的任何过程完成对文件的写入。

不过,根据他们已经设计之后做的,他们可能会被倘若他们写完,文件就不再有混淆(例如,如果他们想要下载后更改文件的某些属性,这样做通过文件描述符(例如chmod()vs fchmod(),或者utimes()无法通过文件描述符完成)。


Shell问题:我想我理解您的代码,但有一个例外。在-exec运行sh一个命令(-c '...')和{} +告诉它同时把多个结果到该命令。我不明白的是为什么sh命令后还有另一个。我想念什么?

2
@Joe,这就是内联脚本的内容$0。也就是说,它为该内联脚本命名。该名称可能会在错误消息中使用,<name>: fuser: command not found例如,因此sh在这种情况下通常是一个很好的选择,以弄清楚报告该错误消息的内容(这也是如果我们在输入错误消息后完全不提供任何参数的情况下的结果)。内联脚本)。
斯特凡Chazelas
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.