我有一个包含文件(各种文件扩展名)和子文件夹的文件夹。我想保留某些文件扩展名并删除其余的。
e.g. keep all .txt and .jpg files and delete all other files.
Run Code Online (Sandbox Code Playgroud)
在常规 UNIX/GNU 上,我可以将 find 与“-not”参数一起使用来实现此目的。
> find . -not -name "*.jpg" -not -name "*txt" -type f -delete
Run Code Online (Sandbox Code Playgroud)
但遗憾的是,这个参数在busybox find 上不可用。
关于如何做到这一点的任何想法?非常感谢
-not并且-delete是非标准扩展。
-not当有一个较短的标准等效项时,您没有理由想要使用!.
对于-delete,您必须rm使用-exec谓词进行调用:
find . ! -name '*.jpg' ! -name '*.txt' -type f -exec rm -f '{}' +
Run Code Online (Sandbox Code Playgroud)
(如果你有一个旧版本的busybox,你可能需要每个文件-exec rm -f '{}' ';'运行一个rm)。
上面的命令是标准的,因此不仅可以在 busybox 中使用,而且可以在其他非 GNU 现代find.
请注意,至少在 GNU 系统上,该命令(find只要它使用 GNU 的任何实现fnmatch(3))可能仍会删除一些名称以.jpg或结尾的文件.txt,因为该*.jpg模式将无法匹配名称在当前语言环境中包含无效字符的文件。
要解决这个问题,您需要:
LC_ALL=C find . ! -name '*.jpg' ! -name '*.txt' -type f -exec rm -f '{}' +
Run Code Online (Sandbox Code Playgroud)
另请注意,与 GNU 的 相反-delete,该方法在非常深的目录树中不起作用,因为您最终会达到传递给unlink()系统调用的文件路径的最大大小。AFAIK,find如果您的find实现不支持-execdir也不支持-delete.
如果您要在其他人可写的目录中运行该命令,您可能还需要阅读GNUfind手册中讨论的安全注意事项。