我有一个正在运行的文件生成器,其中每个文件的名称按字母顺序排列在前一个文件之后。起初我正在做类似的循环for file in /path/to/files*; do...
,但我很快意识到 glob 只会在循环之前扩展,并且循环时创建的任何新文件都不会被处理。
我目前的做法非常丑陋:
while :; do
doneFileCount=$(wc -l < /tmp/results.csv)
i=0
for file in *; do
if [[ $((doneFileCount>i)) = 1 ]]; then
i=$((i+1))
continue
else
process-file "$file" # prints single line to stdout
i=$((i+1))
fi
done | tee -a /tmp/results.csv
done
有没有简单的方法可以循环不断增加的文件列表,而不需要上述的黑客攻击?
答案1
我认为通常的方法是让新文件出现在一个目录中,并在处理后将它们重命名/移动到另一个目录,这样它们就不会再次遇到同一个目录。所以像这样的事情
cd new/
while true; do
for f in * ; do
process file "$f" move to "../processed/$f"
done
sleep 1 # just so that it doesn't busyloop
done
或者类似地改变文件扩展名:
while true; do
for f in *.new ; do
process file "$f" move to "${f%.new}.done"
done
sleep 1 # just so that it doesn't busyloop
done
在 Linux 上,您还可以使用inotifywait
获取有关新文件的通知。
inotifywait -q -m -e moved_to,close_write --format "%f" . | while read -r f ; do
process file "$f"
done
无论哪种情况,您都需要监视仍在写入的文件。就地创建的大文件不会自动显示,但您的脚本可能会在写入一半时开始处理它。
上面的inotifyclose_write
事件将在写入过程关闭文件时看到文件(但它也会捕获修改过的文件),而该create
事件将在第一次创建文件时看到文件(但仍可能被写入)。moved_to
只是捕获移动到正在监视的目录的文件。