将 find -exec 与基本名称一起使用时如何允许目录中存在空格?

将 find -exec 与基本名称一起使用时如何允许目录中存在空格?

我试图找到给定路径中的所有目录,并在这些目录内创建软链接到另一个位置具有相同名称的目录。许多目录的名称中都有空格。我将以下代码拼凑在一起,只要没有空格,它似乎就可以工作。

find /some/path/* -maxdepth 0 -exec sh -c "ln -s /some/other/path/"'$(basename {})'" {}" \;

我应该如何改变它来处理空格?我的目录名称中通常没有它们,但这些镜像目录位于我的 Windows PC 上,我在其中使用空格。任何帮助是极大的赞赏!

编辑

针对cuonglm和Gilles提出的观点:

  • 命令参数的顺序ln -s没有错误,但是从我的解释中我想做什么并不太清楚。对于 中的每个目录/some/path/,我想创建一个符号链接该目录指向 中的同名目录/some/other/path//some/other/path/也是如此,source而且/some/path/也是destination。我想要这样做的原因是因为/some/path/包含 中的目录子集/some/other/path/,并且我想要每个目录的从子集到完整集的链接。

  • 路径中不会有太多目录,但我同意不防范它是一个毫无意义的缺陷。

  • 我没有使用的原因-type d是给定路径中只有目录而不是文件,但我意识到包含它会更好。

答案1

您的命令存在一些问题:

  • /some/path/*如果下面的目录太多,可能会导致参数列表太长错误/some/path

  • 它不过滤目录或文件

  • 它的效率非常低,因为它使用了内联脚本sh -c,但是-exec ... {} \;

  • 使用ln错误的参数位置,将创建从to而不是to 的ln -s source dest符号链接。sourcedestdestsource


你可以用 POSIX 方式做到这一点:

find /some/path ! -path /some/path -prune -type d -exec sh -c '
  for f do
    ln -s "$f" /some/other/path/"${f##*/}"
  done
' sh {} +

或者如果您find支持-maxdepth

find /some/path -maxdepth 1 -type d -exec sh -c '...' sh {} +

答案2

首先,始终{}在 中用作单独的参数find -exec …。使用适用于某些(不是所有)版本的,但不可能处理包含“不寻常”字符的文件名,例如空格、、等(具体哪些字符会导致问题取决于您使用的具体位置)。作为单独的参数传递。之后的第一个参数是.stuff{}morestufffind'"{}{}sh -c CODE$0不要忘记变量扩展周围的双引号

find … -exec sh -c 'ln -s /some/other/path/$(basename "$0") "$0"' {} \;

(我还简化了引用,在全文中使用单引号。)

您的命令至少还存在一个问题。您正尝试在 返回的位置创建符号链接find,通过构造,该位置已经存在符号链接。看来您打算在 下创建一个符号链接/some/other/path,在这种情况下,您需要交换参数ln(与 和 一样mvcp现有文件在前,目标在最后)。

find /some/path/* -maxdepth 0 -exec sh -c 'ln -s "$0" /some/other/path/$(basename "$0")' {} \; 

basename您可以通过使用 shell 字符串操作结构而不是, 并sh一次批量调用来加快速度。

find /some/path/* -maxdepth 0 -exec sh -c '
  for x do
    ln -s "$x" /some/other/path/${x##*/};
  done' {} +

如果这是您的实际find命令,那么find在这里没有用。的要点find是递归到子目录。非递归查找有时对于利用其过滤器很有用(例如,仅对特定类型的文件或在特定时间跨度内修改的文件进行操作)。但是find没有过滤的非递归是没有意义的。

for x in /some/path/*; do
  ln -s "$x" "/some/other/path/${x##*/}";
done' {} +

或者

cd /some/path
for x in *; do
  ln -s "$PWD/$x" "/some/other/path/$x";
done' {} +

或者,与桀骜:

autoload -U zmv
alias zln='zmv -L'
zln -s '/some/path/*' '/some/other/path/$f:t'

相关内容