微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

如何通过linux脚本识别文件是否仍在写入或完成

如何解决如何通过linux脚本识别文件是否仍在写入或完成

我们有一个正在生成文件的系统,我想通过脚本检查许多文件中的哪些文件是完整的,并且在过去两分钟内没有被修改,最后重命名这些文件

这是我尝试过的,但结果不正确。有人可以帮忙吗?

for file in /home/test/*abc_YYYYMMDDhhmmss*
do
    f1=`basename $file`
    if [ lsof | grep "$f1" = "" ];then
        if  [ `stat --format=%Y $file` -le $(( `date +%s` - 300 )) ]; then
        mv "$f1" "${f1}_Complete"
    else
       echo "no files to collect"
    fi
done

解决方法

您犯了一个常见的错误,认为 [if 命令语法的一部分;但它不是:[ 只是另一个命令。 if 语句的语法是

if commands; then
    : what to do if the exit code from commands was 0
else
    : what to do if not
fi

其中 commands 可以是任意复杂的命令序列,序列中最后一个命令的退出代码决定采用哪个分支; else 分支是可选的。

作为最小的修复,更改为

    # use modern $(command substitution) syntax
    # instead of obsolescent `command substitution`;
    # always quote variables with file names
    f1=$(basename "$file")
    # Remove [ and switch to grep -q;
    # add -F to grep flags for literal matching
    if ! lsof | grep -Fq "$f1"; then

无论如何,这样的东西呢?

find $(lsof |
    awk 'NR==FNR { if ($9 ~ /^\/home\/test\//) a[$9]++; next }
    FNR == 1 {
        if (! (FILENAME in a)) print FILENAME;
        next }' - /home/test/*abc_YYYYMMDDhhmmss*) \
    -type f -mmin +2 -exec sh -c '
        for file; do
            mv "$file" "${file}_Complete"
        done' _ {} +

这很复杂,但这里有一个概要。

  • lsof | awk ... 打印出通配符匹配中未打开的文件。
    • 这假定文件是常规文本文件 - 一些 awk 变体在二进制输入文件方面存在问题。如果它是有问题的,那么重构它以避免这种约束可能不会太难。
    • 更详细地说,Awk 的第一个参数是 -,即标准输入,它从 lsof 读取管道。第一个输入文件的条件 NR==FNR 为真;我们只是将打开的文件收集到关联数组 a 中。然后第二个条件打印当前输入文件的名称,如果它不在数组中;这是对剩余的输入文件执行的,即那些匹配通配符的文件。
  • 这作为 find 要检查的路径传递;它将查找在过去两分钟内修改的任何文件,并将结果传递给 -exec 中的命令。
  • -exec 中的简单 shell 脚本应该易于理解。 find 将找到的文件作为命令行参数传递,但 sh -c$0 填充它们,因此我们传入一个虚拟的 _ 以将文件名推送到 {{1} },$1 等等,如果你不给它一个参数列表,这就是 $2 循环的内容。

如果您的文件名包含换行符,这可能不起作用;那么你仍然需要一些更复杂的东西。

在 Bourne 系列 shell 中循环任意文件名令人失望地复杂,并且在 shell 脚本中查找列表中不是的元素总是有点麻烦。 Ksh 和 Bash 提供了一些缓解,因为它们有数组,但这不能移植到 POSIX for / sh / ash

,

这种方式怎么样?

#!/bin/bash
find /home/test/* -type f -mmin +2 -print0 |
    while IFS= read -r -d '' line; do
            echo $line
            fuser -s "$line"
            mv "$line" "${line}_Completed"
    done

-mmin +2 表示最近 2 分钟内未修改的文件。

编辑:根据要求,我已将其更改为 check if the file is currently openfuser -s "$line" 行将退出当前打开的文件,否则它将继续移动文件。我还将变量用引号括起来,感谢提醒

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?