当: busybox find 时不进行批处理。 -执行

当: busybox find 时不进行批处理。 -执行

我只能访问 busybox。

我有一个文件夹,像这样:

prueba/$: ls
./uno
./dos
./tres

每两个子目录(uno、dos)都有许多文件(名称中带有空格和非 ASCII 字符),我想将它们移动到另一个子目录(tres)。

所以我这样做了(转义字符只是因为,确保我在复制和使用 yes 时不会做冗余,只是为了替换目录 [tres] 中已有的任何文件,我之前遇到过 mv -f 问题):

prueba/$: busybox find . -type f -not \( -path . -o -path ./tres \) -exec sh -c ' yes | mv "$1" ./tres ' sh {} \+

但它只移动它找到的第一个文件,然后退出。

但如果我跑:

prueba/$: busybox find . -type f -not \( -path . -o -path ./tres \) -exec sh -c ' yes | mv "$1" ./tres ' sh {} \;

我得到了我所期望的。所有文件都从子目录“uno”和“dos”移动到子目录“tres”。

;当【隐式循环】和+【隐式批处理】到位时,激活的内部机制是什么?

第一个命令行(带有+)有什么问题?

以下是不可能的:

mv -f ./uno/* ./dos/* ./tres/

我正在做一些自动化工作,需要我只运行一行代码并完成工作。另外,这是一个无聊的解决方案。

编辑:

背后的原因find . -exec sh -c 'CMD "$1"' sh {} \;

是否可以安全地使用“find -exec sh -c”?

答案1

将其更改为:

find uno/ dos/ -type f -exec sh -c 'exec mv -f "$@" tres/' sh {} +

您的代码存在的问题:

  • find . -not -path ./tres确实排除./tres,但不排除./tres/any-file-in-it
  • -exec sh 'mv "$1" tres' sh {} +sh使用尽可能多的文件作为参数进行调用,但您只移动第一个 ( $1)。"$@"扩展到全部位置参数作为单独的参数,就像您编写的一样。"$1" "$2" "$3" ... "$last"
  • 注意!作为标准替代非标准-not
  • 请注意,这+在任何 shell 中都不是特殊字符。不需要引用它。
  • 请注意-f选项mv以避免首先提示,这样您就不需要yes。如果您仍然想使用yes,您可以这样做yes | find ... -exec sh -c 'exec mv ...,asshmvwill 继承findstdin 并y从那里读取 s。
  • 通过mvGNU coreutils 和最新版本的实现busybox,您可以sh使用 来避免调用find ... -exec mv -ft tres {} +

如果您想从任何目录(递归地)移动文件,除了当前目录中的文件./tres和排除当前目录中的文件外,您需要:

LC_ALL=C find . -path ./tres -prune -o \
                -path './*/*' -type f -exec sh -c 'exec mv -f "$@" tres/' sh {} +

上面的内容-prune告诉find不要在 中查找文件./tres,而对于其他文件(与so-path './*/*'相结合,匹配任何字节字符串,而不仅仅是字符)限制为路径在前导 后至少包含一个的文件,因此排除 中的文件当前目录。LC_ALL=C*/./

zsh

set -o extendedglob # best in ~/.zshrc
mv -f -- (^tres)/**/*(D.) tres/

但请注意,如果当前目录中存在指向目录的符号链接,则会遵循它们。如果达到系统对参数数量和大小的限制,它也可能会失败(请参阅zargs解决该问题)。

与 相反findzshglob 会对文件列表进行排序,因此,如果有多个同名文件,则最终出现的文件./tres将更具确定性(这将是路径排在最后的文件,但请注意,因为顺序uno排在最后)dos是词汇的;所有其他的都会丢失


1 您可以添加nglob 限定符来获取数字顺序,但这仅适用于数字序列(例如,dir2在之前dir10),uno仍会在之后排序dos

相关内容