Bash脚本迭代目录内容,仅移动当前未被其他进程打开的文件

时间:2017-04-26 17:56:02

标签: linux bash shell

我有人将文件上传到我的Ubuntu服务器上的目录。

只有当我知道这些文件已完全上传时,才需要将这些文件移动到最终位置(另一个目录)。

到目前为止,这是我的剧本:

#!/bin/bash

cd /var/uploaded_by_users

for filename in *; do

        lsof $filename

        if [ -z $? ]; then
          # file has been closed, move it           
        else
          echo "*** File is open. Skipping..."
        fi

done

cd -

然而它没有工作,因为它说有些文件是开放的,但事实并非如此。我认为$?如果文件已关闭则为0;如果不是,则为1,但我认为这是错误的。

我不是linux专家,所以我想知道如何实现这个简单的脚本,每1分钟就会运行一次cron作业。

2 个答案:

答案 0 :(得分:1)

[ -z $? ]检查$?是否为零长度。由于$?永远不会是空字符串,因此检查将始终失败并导致else部分被执行。 您需要测试数字零,如下所示:

lsof "$filename" >/dev/null; lsof_status=$?
if [ "$lsof_status" -eq 0 ]; then
  # file is open, skipping
else
  # move it
fi

或更简单(正如本杰明指出的那样):

if lsof "$filename" >/dev/null; then
  # file is open, skip
else
  # move it
fi

使用否定,我们可以缩短if语句(如dimo414指出的那样):

if ! lsof "$filename" >/dev/null; then
  # move it
fi

您可以使用&&

进一步缩短它
for filename in *; do
  lsof "$filename" >/dev/null && continue  # skip if the file is open
  # move the file
done

答案 1 :(得分:1)

如果要将文件移动到同一文件系统中的其他位置,则可能无需担心写入何时完成。只要客户端使用相同的文件描述符写入文件,您只需为上传文件创建一个新的硬链接,然后删除原始链接。客户端的文件描述符不会受到其中一个链接的影响。

cd /var/uploaded_by_users
for f in *; do
    ln "$f" /somewhere/else/"$f"
    rm "$f"
done