【问题标题】:"dir/*: No such file or directory" with find -exec ... "{}/*"“dir/*:没有这样的文件或目录”与 find -exec ...“{}/*”
【发布时间】:2019-03-04 17:08:21
【问题描述】:

当前目录包含文件和目录。目录没有子目录,但可能包含零个或多个文件,例如:

./file1
./file2
./directory1/file3
./directory2/file4
./directory2/file5
./directory3/

当我执行find . -type d -maxdepth 1 时,我会得到一个目录列表:

./directory1
./directory2

如果我执行mv ./directory1/* .,directory1 中的所有文件都会移动到当前级别.,所以我想我可以使用 find -exec 一次性完成所有操作:

find . -type d -maxdepth 1 -exec mv "{}/*" . \;

但我得到了这样的回应:

mv: rename ./directory1/* to ./*: No such file or directory

如何将子目录中的所有文件移动到当前级别?

【问题讨论】:

    标签: bash macos find


    【解决方案1】:

    没有必要使用find。您可以使用单个 mv 来移动文件并使用 rmdir 来删除现在为空的目录。

    mv */* .
    rmdir */
    

    【讨论】:

    • 是的。问题是,“如何将子目录中的所有文件移动到当前级别?”所以我认为“不需要使用 find”应该是一个答案。
    【解决方案2】:

    通配符(将foo/* 替换为foo/dirAfoo/dirB 等)由shell 执行,而不是由mvfind -exec 不会启动 shell,除非您手动启动;例如:

    find . -type d -mindepth 1 -maxdepth 1 \
           -exec sh -c 'for dir; do mv -- "$dir"/* .; done' _ {} +
    

    【讨论】:

    • 我在 shell 命令中得到了一点,但你能解释一下下划线、大括号和 + 的机制吗? (我知道大括号是找到的目录占位符,但它是如何进入 shell 命令的?)
    • 下划线是$0。大括号被名称替换并变为$1 及以后——也就是说,数组"$@",这是for 默认情况下迭代的内容。将大括号放入 shell 命令将是一个严重的安全漏洞,因为您会将文件名视为代码;如果有人创建了一个包含 $(rm -rf ~) 作为其名称一部分的文件,您不希望执行该文件。 (这些被称为“shell 注入”错误;它们是一类常见的漏洞)。
    • 知道了!谢谢。
    • 顺便说一句,有些人认为他们可以安全地执行-exec sh -c "name='{}'",因为单引号抑制了$() 扩展。但是,$(rm -rf ~)'$(rm -rf ~)' 也是 UNIX 文件名的有效部分,并且名称中的 's 以​​脚本文本中的文字引号结束,因此保持数据完全带外确实需要代码。
    • ...哦,我没有回答你关于-exec ... {} +的问题;这是exec ... {} \; 的替代方案,它为每次调用在命令行上放置尽可能多的名称,因此不是每个文件启动一个shell,而是每批文件启动一个shell。自 2000 年代中期以来,它一直是 POSIX 授权的,因此它不是仅限 GNU 的扩展。
    猜你喜欢
    • 2019-09-06
    • 2018-01-15
    • 2020-08-05
    • 1970-01-01
    • 1970-01-01
    • 2017-04-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多