我正在寻找一个 CLI 工具,它可以监视目录并输出实时变化的文件的名称。
some_watch_command /path/to/some/folder | xargs some_callback
我知道inotify
(inotify-tools
?)并且它似乎就是我需要的,但我需要既兼容 Linux(在我的情况下是 Ubuntu)又兼容 OSX 的东西。
它不需要快如闪电,但需要在变化时触发(一秒钟内是合理的)。此外,我不一定需要上面提到的确切 CLI 程序。如果存在一些底层技术,并且可以轻松地在两个平台上编写脚本,那也很好。
答案1
OS X 通常使用文件夹操作或者已启动来完成这项任务。
我知道的唯一跨平台工具是看门狗APIpip
适用于 Python(因此适用于 OS X 和 Linux)。通过(或easy_install
)安装
pip install watchdog
它附带watchmedo
命令行工具,可让您在系统事件上运行 shell 命令。使用以下命令检查其一般语法:watchmedo --help
这是一个简短的例子,您可以轻松修改以粗体突出显示的命令和路径:
watchmedo shell 命令 \ --递归 \ --命令='回显“${watch_src_path}”' \ /一些/文件夹
这将简单地吐出所有已更改文件或文件夹的路径,允许您将输出通过管道watchmedo
传输到另一个 shell 命令。
答案2
我修改了一些我遇到的 Ruby 脚本,以便完全满足您的要求。以下是 Ruby 代码:
#!/usr/bin/ruby
# Inspired by http://vikhyat.net/code/snippets/#watchfile
# How to use:
# This script takes two paramaters: a folder and a shell command
# The script watches for when files in the folder are changed. When they are, the shell command executes
# Here are some shortcuts you can put in the shell script:
# %F = filename (with extension)
# %B = base filename (without extension)
unless ARGV.length == 2
puts "\e[32m Usage: \e[0mruby OnSaveFolder.rb 'folder' 'command'"
exit
end
require 'digest/md5'
require 'ftools'
$md5 = ''
$directory = File.expand_path(ARGV[0])
$contents = `ls #{$directory}`
$contentsList = $contents.split("\n")
$fileList = []
Dir.chdir($directory)
for i in $contentsList
if ( File.file?(File.expand_path(i)) == true)
$fileList.push(i)
end
end
$processes = []
def watch(file, timeout, &cb)
$md5 = Digest::MD5.hexdigest(File.read(file))
loop do
sleep timeout
if ( temp = Digest::MD5.hexdigest(File.read(file)) ) != $md5
$md5 = temp
cb.call(file)
end
end
end
puts "\e[31m Watching files in folder \e[34m #{$directory}"
puts "\e[32m Press Control+C to stop \e[0m"
for i in $fileList
pid = fork do
$num = 0
$filePath = File.expand_path(i)
watch i, 1 do |file|
puts "\n #{i} saved"
$command = ARGV[1].dup
if ( ARGV[1].include?('%F') )
$command = $command.gsub!('%F', i)
end
if ( ARGV[1].include?('%B') )
$command = $command.gsub!('%B', File.basename(i, '.*'))
end
$output = `#{$command}`
if ( $output != '')
puts "\e[34m #{$command}\e[31m output: \e[0m"
puts $output
end
puts "\e[34m #{$command}\e[31m finished \e[0m (#{$num}, #{Time.now})\n"
$num += 1
end
end
$processes.push(pid)
end
Process.wait(pid)
for i in $processes
`kill #{i}`
end
我将此脚本命名为“OnSaveFolder.rb”。它需要两个参数:您要监视更改的文件夹,以及发生更改时要运行的 bash 代码。例如,
ruby OnSaveFolder.rb '/home/Movies' 'echo "A movie has been changed!"'
希望这能有所帮助!我发现 ruby 非常适合这种类型的工作,并且它默认安装在 OS X 上。
答案3
您可以输入lsof
命令watch
并让其每秒更新一次<s>
:
watch -n <s> lsof
并使用任意过滤器启动它,例如监视 pid1、pid2、pid3 并忽略 pid4
lsof -p "pid1,pid2,pid3,^pid4"
如果这还不够,您可以随时使用 grep 编写自己的过滤器。
对于 OS X,请参阅此问题的答案。
答案4
进入很棒。您可以筛选出您想要它观看的确切文件,就像这样。
find . -name '*.py' | entr python runTests.py
如果您希望它仅监视目录内的某些文件,您可以设计命令find
以便它仅返回您想要监视的文件。
我发现它比 更容易配置fswatch
。