使用bash,我需要查找0字节的文件,但在删除之前报告它们的存在
此问题的历史记录是: 我在NAS系统上有数百万个文件和目录。我发现有1095601个空(0字节)文件。这些文件过去包含数据,但被前一个未使用正确的工具集在XSAN和此Isilon NAS之间迁移数据的文件销毁 这些文件是媒体制作数据,如字体、PDF和图像文件。在它们存在的历史之外,它们不再有用。在我继续删除它们之前,生产用户需要记录哪些文件曾经存在,因此当他们浏览项目文件夹时,他们可以使用未受影响的文件,但随后引用同一目录中的文本文件,该目录记录了哪些文件曾经存在,从而提供了某些引用文件被破坏的原因 那么,如何在多个目录中查找文件并将其删除,但首先将其文件名输出到一个文本文件,该文件将保存到每个相关路径位置 我的思路是:使用bash,我需要查找0字节的文件,但在删除之前报告它们的存在,bash,find,Bash,Find,此问题的历史记录是: 我在NAS系统上有数百万个文件和目录。我发现有1095601个空(0字节)文件。这些文件过去包含数据,但被前一个未使用正确的工具集在XSAN和此Isilon NAS之间迁移数据的文件销毁 这些文件是媒体制作数据,如字体、PDF和图像文件。在它们存在的历史之外,它们不再有用。在我继续删除它们之前,生产用户需要记录哪些文件曾经存在,因此当他们浏览项目文件夹时,他们可以使用未受影响的文件,但随后引用同一目录中的文本文件,该目录记录了哪些文件曾经存在,从而提供了某些引用文件被破坏的
for file in $(find . -type f -size 0); do
echo "$file" >> /PATH/TO/FOUND/FILE/PARENT/DIR/deletedFiles.txt -print0 |
xargs -0 rm ;
done
为什么不简单
find . -type f -size 0 -exec rm -v + |
sed -e 's%^removed .\./%%' -e 's/.$//' >deletedFiles.txt
如果您的查找
太旧,无法支持-exec+
您需要恢复到-execrm-v{}代码>或重构到
find . -type f -size 0 -print0 |
xargs -r -0 rm -v |
sed -e 's%^removed .\./%%' -e 's/.$//' >deletedFiles.txt
简短的sed
脚本用于对rm-v
的输出进行后处理,如下所示
removed ‘./bar’
removed ‘./foo’
(文件名周围有一些有趣的引号字符)在我的系统上。当然,如果您对该输出没有意见,只需从管道中省略sed
脚本即可
如果您事先知道哪些目录包含空文件,则可以在这些目录中单独运行上述代码段。假设您将上面的代码段保存为名为find empty
的脚本(具有适当的shebang和execute权限),您只需使用
for path in /path/to/first /path/to/second/directory /path/to/etc; do
cd "$path" && find-empty
done
只有当您有绝对路径时,这才有效(如果没有,您可以通过在子shell中添加括号来运行循环体)
如果要检查树中的所有目录,请将脚本改为“打印到标准输出”(从脚本中删除>deletedFiles.txt
),然后尝试以下操作
find /path/to/tree -type d -exec sh -c '
t=$(mktemp -t find-emptyXXXXXXXX)
cd "$1" &&
find-empty | grep . >"$t" &&
mv "$t" deletedFiles.txt ||
rm "$t"' _ {} \;
这将使用临时文件,以避免更新不包含任何空文件的目录的时间戳。grep.
纯粹用于副作用;如果打印任何(非空)行,将返回成功,否则将报告失败;这样,我们就知道是否将临时文件移动到目标目录。要删除每个空文件,同时留下一个名为deletedFiles.txt的文件,其中包含已删除文件的名称,请尝试:
PATH=/bin:/usr/bin find . -empty -type f -execdir bash -c 'printf "%s\n" "$@" >>deletedFiles.txt' none {} + -delete
工作原理
PATH=/bin:/usr/bin
这将设置一个临时但安全的路径
查找。
这将开始查找当前目录中的find
-空的
这告诉find
只查找空文件
-类型f
这将find
限制为查找常规文件
-execdir bash-c'printf“%s\n”“$@”>>deletedFiles.txt'none{}+
在每个包含空文件的目录中,这会将每个空文件的名称添加到文件deletedFiles.txt
请注意命令中none
的特殊用法:
bash -c 'printf "%s\n" "$@" >>deletedFiles.txt' none {} +
运行此命令时,bash
将执行字符串printf“%s\n”$@>>deletedFiles.txt
,该字符串后面的参数将分配给位置参数:$0
,$1
,$2
,等等。使用$
时,它不包括$0
。它通常扩展为$1
,$2
。。。。因此,我们添加了占位符none
,以便将占位符分配给$0
,我们将忽略该占位符,并将完整的文件名列表分配给“$@”
-删除
这将删除每个空文件
在@JonathanLeffler的提示下,我成功地实现了以下目标:
#!/bin/bash
## call this script with: find . -type f -empty -exec handleEmpty.sh {} +
for file in "$@"
do
file2="$(basename "$file")"
echo "$file2" >> "$(dirname "$file")"/deletedFiles.txt
rm "$file"
done
这意味着我会在每个目录中的deletedFiles.txt标志文件中保留删除文件的跟踪,以便用户查看文件何时丢失。这样,他们就可以继续回到归档CD中检索这些已删除的文件,希望这些文件不是0字节的文件
感谢@John1024建议使用空
标志而不是大小
你真的需要更仔细地解释你需要做什么。看起来您需要查找大小为0的文件,对于每个这样的文件,将名称记录在找到该文件的目录中的deletedFiles.txt
文件中,并删除该文件。您的echo
命令将名称和-print0
回显到一个文件名(可能不存在),然后运行xargs
,而不进行任何输入,因为echo
被发送到一个文件,因此xargs
只运行rm
,没有触发rm
警告的参数。-print0
可能属于find
。如果是我的问题,我会使用find-键入f-size 0-exec special-script.sh{}+
以生成名称列表和special script.sh
将依次处理其每个参数,处理回显、文件名路径和删除(对于“$@”中的文件;do echo“$file”>”$(dirname“$file”)/deletedFiles.txt;rm“$file”;done
或大约). 虽然这可能不需要两个脚本就可以完成,但对于像我这样懒散的人来说,这太像是一项艰苦的工作了。@JonathanLeffler我已经成功地完成了你的输入。谢谢。如果不是因为-print0
,你也可以在管道中使用tee
。我尝试了你的第二种选择