在具有变量扩展的 bash 脚本中查找 -exec

在具有变量扩展的 bash 脚本中查找 -exec

我正在尝试在 bash 脚本中运行类似于下面的命令。它应该搜索 的所有子文件夹$sourcedir并将某种类型的所有文件复制到 的根级别$targetdir

#!/bin/bash

# These are set as arguments to the script, not hard-coded
sourcedir="/path/to/sourcedir"
targetdir="/path/to/targetdir"

find "$sourcedir" -type f -name "*.type" -exec sh -c 'cp "$1" "$2/`basename "$1"`"' "{}" "$targetdir" \;

这似乎非常接近,除了{}没有被传递$2-exec sh -c ...

我想尽可能接近“正确的方式”,并容忍文件名中的特殊字符(特别是单引号字符)。

编辑:我看到有人建议使用xargs或参数链。我的印象是,这只适用于有限数量的参数。例如,如果我有数千个 .jpg 文件,我试图从多个图库目录复制到一个巨大的幻灯片目录中,那么链接参数的解决方案仍然有效吗?

编辑2:_我的问题是我在命令中的第一个选项 sh 之前缺少了 a -exec。对于任何对如何使 find 命令起作用感到好奇的人,添加 ,_一切都会好起来的:

find "$sourcedir" -type f -name "*.type" -exec sh -c 'cp "$1" "$2"' _ "{}" "$targetdir" \;

我接受了下面的答案,因为它完成了相同的任务,但更高效和优雅。

答案1

您想将特定类型的文件复制到特定目录吗?最好这样做xargs,而且您甚至不需要它sh。这是一个比较合适的做法,也应该运行得更加高效。

find "$sourcedir" -type f -name "*.type" | xargs cp -t targetdir

如果您需要处理特殊文件名,请使用NULL作为分隔符

find "$sourcedir" -type f -name "*.type" -print0 | xargs -0 cp -t "$targetdir"

答案2

您需要将{}其作为参数传递给 shell,然后循环遍历每个参数。

find "$sourcedir" -type f -name "*.type" -exec sh -c 'for f; do cp "$f" "$0"; done' "$targetdir" {} +

笔记:它的工作方式是 shell 的第一个参数是外壳名称,我们可以通过将名称作为 the 传递,然后使用shell 脚本中的$targetdir特殊参数来访问该目标目录来利用这一点。$0

答案3

如果你不相信 xargs 教会:

find "$sourcedir" -type f -name "*.mp3" -exec cp -t "$targetdir" {} +

解释:

cp -t a b c d 

将 b、c 和 d 复制到目标目录 a。

-exec cmd {} +

一次对一大堆文件调用该命令,而不是一个接一个地调用(这是标准的,如果您使用";"而不是+)。这就是为什么我们必须将 targetdir 拉到前面并将其显式标记为目标。

这适用于 gnu-find,但可能不适用于 find 的其他实现。当然它也依赖于 -t -标志。

TechZilla 当然位于最右边,因为sh不需要调用 cp。

如果您不使用xargs,大多数情况下不需要与 结合使用find,那么您就无需学习-print0-0标志。

答案4

read -p "SOURCE: " sourcedir
read -p "TYPE: " type
read -p "TARGET: " targetdir
find -L $sourcedir -iname "*.$type" -exec cp -v {} $targetdir \;

相关内容