监视文件夹中是否有新文件的脚本?

iha*_*ter 178 shell filesystems monitoring directory files

如何立即检测何时将新文件添加到脚本中的文件夹?我希望脚本在文件夹中创建文件后立即处理文件。除了安排每分钟左右检查新文件的作业之外,还有其他方法吗?

enz*_*tib 212

您应该考虑使用inotifywait, 作为示例:

inotifywait -m /path -e create -e moved_to |
    while read dir action file; do
        echo "The file '$file' appeared in directory '$dir' via '$action'"
        # do something with the file
    done
Run Code Online (Sandbox Code Playgroud)

在 Ubuntu 中inotifywait是由inotify-tools包提供的。从 3.13 版开始(当前在 Ubuntu 12.04 中)inotifywait将包含不带 -f 选项的文件名。旧版本可能需要强制执行。需要注意的是,-e选项inotifywait是进行事件过滤的最佳方式。此外,您的read命令可以将位置输出分配给您可以选择使用或忽略的多个变量。不需要使用 grep/sed/awk 来预处理输出。

  • @Wender inotfiywait 在触发时在一行上输出 3 条信息。'read' bash 内置函数读取输入行并将三个信息中的每一个分配给一个变量。因此,第一部分分配给变量路径,第二部分分配给操作,第三部分分配给文件。为这些变量赋值后,它们就可以在以后使用(如在回声线上)。更多信息:https://www.tldp.org/LDP/Bash-Beginners-Guide/html/sect_08_02.html (5认同)
  • 伟大的!`inotifywait` 正是我想要的。 (2认同)
  • 只想更新这个。你不需要 awk 来实现这一点。您可以使用“-e create”过滤事件,并通过“-f %f”或使用“-f %w%f”获取完整路径来仅获取文件名。所以上面脚本的第一行变成了:inotifywait -m /path -f %w%f -e create | (2认同)
  • @Lugoues,现在当您尝试使用 -f 时,您会发现“'--filename' 选项不再存在。它在早期版本的 inotifywait 中启用的选项现在默认打开。` 因此,您只需执行`inotifywait -m /path -e create |` 我将尝试编辑此答案。 (2认同)
  • 现在还有一个名为 [`fswatch`](http://emcrisostomo.github.io/fswatch/) 的便携工具。我没有写它,但它是开源的,我使用它。 (2认同)
  • 对于 CentOS:`yum --enablerepo=epel -y install inotify-tools` (2认同)

Gyp*_*aut 41

您可以watch在脚本中使用

watch -n 0.1 ls <your_folder>
Run Code Online (Sandbox Code Playgroud)

监控您的文件夹并每 0.1 秒列出其中的所有内容

退税

不是实时的,所以如果一个文件在0.1秒内被创建和删除,那么这将不起作用,watch只支持最小0.1秒。


Mic*_*chi 34

我只是编造了这个,并没有发现它有什么大问题,除了在检查之间丢失文件的可能性很小。

while true
do
       touch  ./lastwatch
       sleep 10
       find /YOUR/WATCH/PATH -cnewer ./lastwatch -exec SOMECOMMAND {} \;
done
Run Code Online (Sandbox Code Playgroud)

如果您的文件处理不会花费太长时间,您就不应该错过任何新文件。你也可以为活动做背景......它不是防弹的,但它可以在没有inotify等外部工具的情况下用于某些目的。

  • 如果 `inotify` 不可用,最佳解决方案。我会添加`-type f` 来过滤掉文件。否则文件夹也将被返回。 (5认同)

小智 27

我更喜欢incron,因为它更易于管理。本质上,它是一种利用的服务,inotify您可以设置配置以根据文件更改操作采取行动。

前任:

<directory> <file change mask> <command or action>  options
/var/www/html IN_CREATE /root/scripts/backup.sh
Run Code Online (Sandbox Code Playgroud)

你可以在这里看到一个完整的例子:http : //www.cyberciti.biz/faq/linux-inotify-examples-to-replicate-directories/


Eva*_*oll 16

entr

使用entr是执行此操作的新方法(它是跨平台的)。Noteentr不使用轮询,使其比许多替代方案具有巨大优势。

使用kqueue(2)inotify(7)来避免轮询。entr编写的目的是使快速反馈和自动化测试自然而完全普通。

在 BSD 上它使用 pledge(2)

你可以安装它

apt-get install entr
dnf install entr
brew install entr
Run Code Online (Sandbox Code Playgroud)

您可以使用以下方法跟踪新添加的目录

while $(true); do
  # echo ./my_watch_dir | entr -dnr echo "Running trigger..."
  echo ./my_watch_dir | entr -dnr ##MY COMMAND##
done;
Run Code Online (Sandbox Code Playgroud)

选项解释(来自文档),

  • -d 跟踪作为输入提供的常规文件的目录,如果添加了新文件则退出。此选项还允许显式指定目录。名称以“.”开头的文件 被忽略。
  • -n在非交互模式下运行。在此模式下,entr 不会尝试从 TTY 读取或更改其属性。
  • -r 重新加载一个持久的子进程。与标准操作模式一样,在处理文件系统或键盘事件之前,不会再次执行终止的实用程序。 SIGTERM用于在重新启动之前终止该实用程序。创建进程组是为了防止 shell 脚本屏蔽信号。 entr等待实用程序退出以确保诸如套接字之类的资源已关闭。TTY 的控制权不转移给子进程。

注意entr不是在那里投票。这是在它没有看到的 inode 上进行操作之后。请注意,这不是故障安全机制,因为 inode 可以完全回收为不同的文件名。IE,

apt-get install entr
dnf install entr
brew install entr
Run Code Online (Sandbox Code Playgroud)

请参阅inotifywait答案以获得更好,更强大的方法。尽管界面更糟糕。


zta*_*013 10

我假设目标文件夹(isempty为了方便起见,我将其称为)是空的,并且您正在等待一个或多个文件放到那里。

您可以使用以下命令:

ls -1A isempty | wc -l
Run Code Online (Sandbox Code Playgroud)

只是为了检查文件夹是否仍然是空的,实际上如果没有新文件(因此isempty文件夹仍然是空的),它会返回一个 0,或者另一方面,它会返回一个大于 0 的值(实际上是数字当前在文件夹中的文件)。

也就是说,一个愚蠢的 if/then 测试可以完成其余的工作:

if [ $(ls -1A isempty | wc -l) -gt 0 ] ; then do_something ; fi
Run Code Online (Sandbox Code Playgroud)

当然,该do_something函数必须操作文件isempty夹内的文件,然后在处理后将其从文件夹本身中删除。

在您的 crontab 中添加如下一行将每分钟运行一次检查do_something,当然如果文件夹不为空,则会触发操作:

* * * * *     if [ $(ls -1A isempty | wc -l) -gt 0 ] ; then do_something ; fi
Run Code Online (Sandbox Code Playgroud)

  • 你永远不应该使用 `ls` 来编写脚本。改用`find` 或简单的通配符:http://mywiki.wooledge.org/ParsingLs (3认同)

小智 9

如果你想检测新文件,然后处理它们,最后删除处理过的文件,你可以使用systemd.path。该方法基于inotify。有一个选项 DirectoryNotEmpty,因此 systemd 可以在检测到目录中的任何文件时始终运行您的脚本。您必须记住,只有当您可以删除处理过的文件并且脚本将目录留空时,它才会起作用。

首先准备mymonitor.service文件

[Unit]
Description=Start the script

[Service]
Type=oneshot
ExecStart=/path/to/your/script
Run Code Online (Sandbox Code Playgroud)

接下来去 mymonitor.path 定义路径

[Unit]
Description= Triggers the service

[Path]
DirectoryNotEmpty=/path/to/monitor

[Install]
WantedBy=multi-user.target
Run Code Online (Sandbox Code Playgroud)

如果 .path 文件的名称与服务名称相同,则无需在 .path 文件中指定服务名称。

它基于监视傻瓜的文件访问