![Split 在 bash 中表现得很奇怪](https://linux22.com/image/12361/Split%20%E5%9C%A8%20bash%20%E4%B8%AD%E8%A1%A8%E7%8E%B0%E5%BE%97%E5%BE%88%E5%A5%87%E6%80%AA.png)
尝试将 split 与 inotifywait 一起使用,当从 ftp 服务器创建文件时,它基本上会拆分文件。
#!/bin/bash
TARGET=/home/test-directory/incoming
SPLITTED=/home/test-directory/incoming/splitted
PROCESSED=/home/test-directory/incoming/processed
LOGFILE=/var/log/inotify-ftp.log
inotifywait -m -e create -e moved_to --format "%f" $TARGET \
| while read FILENAME
do
echo Detected $FILENAME >> $LOGFILE
echo Splitting $FILENAME >> $LOGFILE
split -d -l 1000 "$TARGET/$FILENAME" "$SPLITTED/$FILENAME"
#/usr/bin/split -d -l 1000 /home/test-directory/incoming/test-file.csv /home/test-directory/incoming/splitted/test-file.csv
mv "$TARGET/$FILENAME" "$PROCESSED/$FILENAME"
echo Completed splitting $FILENAME >> $LOGFILE
done
因此,下面的代码在单独执行时工作正常。上面的脚本应该做同样的事情,但它创建了第一个只有几百行的分割文件。
#/usr/bin/split -d -l 1000 /home/test-directory/incoming/test-file.csv /home/test-directory/incoming/splitted/test-file.csv
知道吗,发生了什么事?
答案1
这是因为文件在创建时长度为零。有一个竞争条件,其中 split 计算出文件的大小,并决定如何分割它,而 ftp-server 很高兴地一直让它变得更大。
明智的做法是建立一种机制,让分割等待文件完全到达后再开始读取。通常,循环统计文件,直到它在前一分钟不再增长。
答案2
正如已经解释过的别处当文件(刚刚)创建时触发create
事件,而不引用正在添加的内容。将事件inotifywait
更改create
为,close_write
以便在文件传输服务关闭文件之前不会触发:
inotifywait -m -e close_write -e moved_to --format "%f" "$TARGET"
您还应该构建一些错误处理功能,以便您的进程可以区分完全传输的文件和中途中断的文件。这可能是检查文件内容的有效性,或者使用tmp
发送者在成功传输时重命名文件时删除的后缀来传输文件,等等。
最后,作为良好的编码实践,请记住在使用变量的任何地方都用双引号引起来。