【问题标题】:Multiple 'find' for watchers at once - only executes first one一次为观察者进行多个“查找” - 仅执行第一个
【发布时间】:2019-07-03 14:59:11
【问题描述】:

我正在尝试运行一个脚本来监视不同的文件夹和文件,如果它们发生变化,请执行一个命令。其中一个文件夹路径接受一个动态变量,该变量将根据在 CLI 中运行脚本时输入的内容而改变,而另一个则不会改变。

但是,根据文件路径,需要采取不同的操作。

#!/usr/bin/env bash

THEME=$1

while true;
do
  echo "inside find"
    find code/themes/$THEME/src -name '*.html' -o -name '*.ts' -o -name '*.scss' | entr -d rsync -avh code/themes/$THEME/*  ./
    find code/base/src -name '*.html' -o -name '*.ts' -o -name '*.scss' | entr -d rsync -avh code/base/*  ./
done

当我运行脚本时发生的事情是它只执行并将手表放在第一个 find 上(在上面粘贴的代码示例中,仅动态路径)。

目前我的问题是:

  • 只有第一个 find 被调用,并且只有一个 watch 放置在 code/themes/$THEME/src 路径上
  • 第二个发现永远不会被执行

如何让两者同时运行?或者,我怎样才能在一行中写完?

另外,我以前从未编写过脚本或使用过 bash,所以如果您对重构有任何建议或能够帮助解决我的问题,请在技术解释方面保持温和。

我的主要目标是:

  1. 我想设置一个监视路径代码/主题/$THEME/src 中的任何更改
  2. 我想设置一个监视路径代码/base/src 中的任何更改
  3. 我希望两个观察者同时运行

【问题讨论】:

  • entr 显然来自this answer,您被定向到yesterday.
  • 我不熟悉entr,但如果我没看错的话,它会运行第一个findentr 管道,然后运行第二个find 并坐在那里等待任何列出的文件都可以更改。
  • 顺便说一句,您应该在$THEME 周围使用双引号,或者实际上使用小写的变量名(大写保留给系统使用)。即使您从未期望参数包含 shell 元字符,如果您尝试传入需要引用的参数,当您使用不带引号的参数时,错误消息也会令人困惑。进一步查看When to wrap quotes around a shell variable?
  • @tripleee 是的,在您提到与我的其他问题类似的问题后,我正在玩 entr。现在在基于路径的不同命令的多个查找中面临这个问题。感谢您对语法约定的建议。我会执行的。
  • 也许你应该更详细地解释你希望发生的事情。这些顺序执行是否有原因?如果您有两个彼此独立运行的 while 循环会怎样?

标签: bash shell find watch


【解决方案1】:

如果您的任务只是确保两个(或 1 + 个主题)目录的下游副本始终是最新的,cron 作业每 n 分钟同步一次它们可能是最简单和最强大的解决方案。 cron 具有每分钟的粒度,但对于您的用例来说,每五分钟一次可能就足够了。 rsync 按照设计不会复制已经是最新的文件,因此在无操作情况下执行应该相当快。

* * * * * bin/rsyncthemes

(这是每分钟一次;在 Linux 上,您可以在第一个字段中说 */5 以每 5 分钟运行一次,但这不适用于所有 cron 方言。)...其中rsyncthemes 包含一些内容喜欢

#!/bin/sh
# cron jobs always start in your home directory,
# but you want to put an absolute path here
# to run this in the directory where you want rsync to copy these files
cd somewhere

for dir in code/themes/one \
    code/themes/other \
    code/base
do
    rsync -avh "$dir"/*  ./
done

显然这需要标记为可执行文件 (chmod a+x rsyncthemes) 并保存在我们在 cron 作业中指定的目录中(即您的主目录中的 bin)。

如果你一心想要使用entr 来避免不必要地运行rsync,我猜你想要类似的东西

for dir in code/themes/one \
    code/themes/other \
    code/base
do
    while true; do
        find "$dir"/src -name '*.html' -o -name '*.ts' -o -name '*.scss' |
        entr -d rsync -avh "$dir"/*  ./
    done & # <-- run each loop as a background job
done

更详细地说,我们正在运行三个while true 循环作为后台作业,一个用于for 循环中枚举的每个目录。它们与您的交互式 shell 并行运行,并在您注销时停止运行(除非您单独将它们设置为使用 nohup 之类的东西继续运行)。 &amp; 运算符是在后台运行的东西,将其放在 while 循环的 done 语句之后使其适用于整个循环。

我猜您可能需要使用 entr -n 才能让作业在后台运行。

rsync 命令中的通配符由 shell 扩展,因此您可能需要重构它以不使用通配符,或者仅在 find 完成后评估通配符,如果您希望它可以用于新文件偶尔会出现在这些目录中。 (如果我正确阅读了entr 手册页,引用整个rsync 命令并使用entr -s 传递它应该可以轻松完成。)

【讨论】:

  • 我用 entr 实现了解决方案,它正在工作!谢谢你!我会研究你提到的一些东西,并在我玩弄它时应用它们。再次感谢。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-07
  • 2019-05-14
  • 2023-03-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多