我有这个文件夹结构:
leave_type
服务器正在监视incoming/
Printing/
|------ done/
\------ error/
文件夹,等待Printing
文件出现在其中。检测到新文件后,它将发送到打印机,并在成功时将其移动到.txt
或在失败时将其移动到done
。
我正在处理的脚本必须执行以下操作:扫描error
目录中的文件,并将它们一个接一个地传输到incoming
文件夹中。我从在StackOverflow上找到的这个脚本开始:
Printing
问题在于它检测到两个子文件夹#!/usr/bin/env bash
while true; do
target="/var/www/test";
dest="/var/www/incoming";
find $dest -maxdepth 1 -type f | sort -r | while IFS= read -r file; do
counter=0;
while [ $counter -eq 0 ]; do
if find "$target" -maxdepth 0 -mindepth 0 -empty | read; then
mv -v "$file" "$target" && counter=1;
else
echo "Directory not empty: $(find "$target" -mindepth 1)"
sleep 2;
fi;
done;
done
done
和done
并拒绝复制文件,始终发出“目录不为空”消息。
我需要一种使脚本忽略那些文件夹的方法。
我尝试了error
命令中涉及find
和-prune
的变体,但是没有发现任何有效的方法。如何根据自己的需要在内部循环中修复! -path
命令?
答案 0 :(得分:0)
有问题的命令是这样的:
find "$target" -maxdepth 0 -mindepth 0 -empty
首先要认识到它的作用:
"$target"
命名的目录(如果有)上运行
-maxdepth 0
,它仅测试 该路径本身-empty
谓词匹配 empty 常规文件和目录-mindepth 0
是默认设置;明确表示它没有其他作用)由于您期望目标目录从不为空(它将至少包含您描述的两个子目录),因此您需要一种不基于-empty
的方法谓语。 find
无法调节“空”的含义。
有多种方法可以解决此问题,有些包括find
,而有些则没有。由于find
有点重量级,并且对于复杂的测试来说它的参量语法有些晦涩,因此我建议使用以下替代方法:ls
+ grep
。示例:
# File names to ignore in the target directory
ignore="\
.
..
done
error"
# ...
while /bin/true; do
files=$(ls -a "$target" | grep -Fxv "$ignore")
if [ -z "$files" ]; then
mv -v "$file" "$target"
break
else
# non-ignored file(s) found
echo "Directory not empty:"
echo "$files"
sleep 2
fi
done
注意事项:
-a
选项被提供给ls
来捕获点文件,从而匹配find
的{{1}}谓词的行为。相反,您可能更愿意忽略点文件,在这种情况下,您可以简单地删除-empty
。
-a
的{{1}}选项指定它要匹配固定字符串(不是模式),而F
选项告诉它必须匹配整行。 grep
选项颠倒了匹配的含义,因此这三者共同导致匹配行(文件名),而不是-x
变量中指定的行。
将文件列表捕获到一个变量中比重新计算它更有效,并且避免了在文件移动之前就检测到文件的竞争情况。通过捕获文件列表,您可以确保重新概括脚本决定延迟的基础数据。
文件名可能包含换行符,精心设计的包含换行符的文件名可能会使该脚本误认为目录(实际上)为空,而实际上却不是。如果您对此感到担忧,那么您将需要更强大的功能,也许毕竟使用-v
。