Bash: 查找排除目录错误
Bash: Find exclude directory error
我有这个文件夹结构:
incoming/
Printing/
|------ done/
\------ error/
服务器正在监视 Printing
文件夹,等待 .txt
文件出现在其中。当检测到新文件时,它会将其发送到打印机并在成功时将文件移动到 done
或在失败时移动到 error
。
我正在处理的脚本必须执行以下操作:扫描 incoming
目录中的文件,并将它们一个一个地传输到 Printing
文件夹中。我从在 Whosebug 上找到的这个脚本开始:
#!/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
并拒绝复制文件,总是发出 "Directory not empty" 消息。
我需要一种方法让脚本忽略这些文件夹。
我尝试了涉及 -prune
和 ! -path
的 find
命令的变体,但我没有找到任何有效的方法。如何修复内循环中的 find
命令以按我的要求执行?
有问题的命令是这样的:
find "$target" -maxdepth 0 -mindepth 0 -empty
从认识它的作用开始:
- 它在由
"$target"
命名的目录(如果有)上运行
- 因为
-maxdepth 0
,它只测试 该路径本身
-empty
谓词匹配空 常规文件和目录
- (
-mindepth 0
是默认值;明确表达它没有任何附加效果)
由于您期望目标目录 永远不会 为空(它将至少包含您描述的两个子目录),因此您需要一种不基于-empty
谓词。 find
无法调整 "empty" 的含义。
有多种方法可以解决这个问题,有些包括 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
的 -empty
谓词的行为。您可能更愿意忽略点文件,在这种情况下,您可以简单地删除 -a
.
grep
的F
选项指定匹配固定字符串(不是模式),-x
选项告诉它必须匹配整个字符串线。 -v
选项反转了匹配的含义,因此这三个选项一起导致匹配行(文件名)与 ignore
变量中指定的行(文件名)不同。
在变量中捕获文件列表比重新计算它更有效,并且避免了在文件移动之前检测到文件的竞争条件。通过捕获文件列表,您可以确保重述脚本决定延迟所依据的确切数据。
文件名可能包含换行符,精心制作的包含换行符的文件名可能会欺骗此脚本,使该脚本认为目录(实际上)是空的,而实际上它不是。如果这对您来说是一个问题,那么您将需要更强大的东西,也许毕竟使用 find
。
我有这个文件夹结构:
incoming/
Printing/
|------ done/
\------ error/
服务器正在监视 Printing
文件夹,等待 .txt
文件出现在其中。当检测到新文件时,它会将其发送到打印机并在成功时将文件移动到 done
或在失败时移动到 error
。
我正在处理的脚本必须执行以下操作:扫描 incoming
目录中的文件,并将它们一个一个地传输到 Printing
文件夹中。我从在 Whosebug 上找到的这个脚本开始:
#!/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
并拒绝复制文件,总是发出 "Directory not empty" 消息。
我需要一种方法让脚本忽略这些文件夹。
我尝试了涉及 -prune
和 ! -path
的 find
命令的变体,但我没有找到任何有效的方法。如何修复内循环中的 find
命令以按我的要求执行?
有问题的命令是这样的:
find "$target" -maxdepth 0 -mindepth 0 -empty
从认识它的作用开始:
- 它在由
"$target"
命名的目录(如果有)上运行
- 因为
-maxdepth 0
,它只测试 该路径本身 -empty
谓词匹配空 常规文件和目录- (
-mindepth 0
是默认值;明确表达它没有任何附加效果)
由于您期望目标目录 永远不会 为空(它将至少包含您描述的两个子目录),因此您需要一种不基于-empty
谓词。 find
无法调整 "empty" 的含义。
有多种方法可以解决这个问题,有些包括 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
的-empty
谓词的行为。您可能更愿意忽略点文件,在这种情况下,您可以简单地删除-a
.grep
的F
选项指定匹配固定字符串(不是模式),-x
选项告诉它必须匹配整个字符串线。-v
选项反转了匹配的含义,因此这三个选项一起导致匹配行(文件名)与ignore
变量中指定的行(文件名)不同。在变量中捕获文件列表比重新计算它更有效,并且避免了在文件移动之前检测到文件的竞争条件。通过捕获文件列表,您可以确保重述脚本决定延迟所依据的确切数据。
文件名可能包含换行符,精心制作的包含换行符的文件名可能会欺骗此脚本,使该脚本认为目录(实际上)是空的,而实际上它不是。如果这对您来说是一个问题,那么您将需要更强大的东西,也许毕竟使用
find
。