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

标签 linux shell sh lsof

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

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

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 为 true;我们只需将打开的文件收集到关联数组a中。然后第二个条件打印当前输入文件的名称(如果它不在数组中);这是针对剩余的输入文件执行的,即那些与通配符匹配的文件。
  • 这将作为 find 进行检查的路径传递;它将查找最近两分钟内修改的所有文件,并将结果传递给 -exec 中的命令。
  • -exec 中的简单 shell 脚本应该很容易理解。 find 将找到的文件作为命令行参数传递,但 sh -c$0 填充它们,因此我们传入一个虚拟 _ 将文件名插入 $1$2 等,如果您不给它一个列表,这就是 for 循环的内容论据。

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

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

关于linux - 如何通过linux脚本识别文件是否仍在写入或完成,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65856423/

相关文章:

linux - 为什么我在 shell 中键入 linux 中的时间命令与在脚本中使用它时输出不同?

linux - 在busybox的ash下做算术时如何将八进制数视为十进制数

bash - jq : command not found in GitLab CI file

java - BPXWUNIX : not found error when trying to run Regina Rexx script

c -/bin/sh依赖哪些POSIX系统接口(interface)?

在 linux 中使用其他库创建共享库

java - 如何在 Tomcat/linux 服务器上配置 kerberos?

linux - 如何检查文件大小是否没有增加,如果没有则杀死脚本的$$

linux - 在 shell 中使用 "<"比较两个参数

python - 如何在 Windows Powershell 中从 Python 调用 shell 脚本?