`find` 和 `rename` – 没有这样的文件或目录

`find` 和 `rename` – 没有这样的文件或目录

我想删除子目录中文件名中的点。我使用renamefind

 find . -type f -name '*.avi' -exec rename 's/\.(?=[^.]*\.)/ /g' {} \;

该命令find单独运行。 该命令rename单独运行。 但是当我同时使用两者时,我收到错误:

No such file or directory 

如何让它们协同工作?


我测试了这个但它不起作用:

mkdir test
cd test
mkdir f1
cd f1
touch {1..20}-file.with.dot.avi
cd ..
cp -r  f1/ f2
cd ..
find . -type f -name '*.avi' -exec  rename   's/\.(?=[^.]*\.)/ /g' "{}" \;

我测试了这个,但是不起作用

mkdir test
cd test
mkdir f1
cd f1
touch {1..20}-file.with.dot.avi
cd ..
cp -r  f1/ f2
cd ..
find . -type f -name '*.avi' -exec  rename   's/\.(?=[^.]*\.)/ /g' "{}" \;

答案1

笔记rename很多。OP 的rename似乎是 Perl rename(有时称为prename)。一般来说rename 可能会或可能不会运行 Perlrename


错误如下:

Can't rename ./test/f1/1-file.with.dot.avi  /test/f1/1-file with dot.avi: No such file or directory

请注意,目标路径毫无意义。它看起来是绝对路径,但实际上它不是以 开头的/。它以空格字符开头。这是因为前导点 ( .) 被空格字符替换了。没有目录<space>/test/f1/rename也不会创建它,因此No such file or directory

之所以有点,是因为find必须以用户提供的路径之一来开始路径名,并且您提供.该路径。

解决方案有以下几种:

  • 不要用作.起始路径。例如:

    find "$PWD" -type f -name '*.avi' -exec rename 's/\.(?=[^.]*\.)/ /g' {} \;
    

    请注意,如果任何目录名中有一个点(在$PWD扩展到的或下面的某个目录中),那么您很可能会遇到同样的问题。

  • 重新添加缺失的点:

    find . -type f -name '*.avi' -exec rename 's/\.(?=[^.]*\.)/ /g; s/^ /./' {} \;
    

    这不是一个通用的解决方案。同样,如果任何路径名包含带有 的目录组件,则会出现问题.

  • 如果您find支持-execdir,请使用它。生成的路径名将类似于./1-file.with.dot.avi目录名中的点将变得无关紧要。但您仍需要处理这个前导点。示例:

    # re-adding dot like in the above approach
    find . -type f -name '*.avi' -execdir rename 's/\.(?=[^.]*\.)/ /g; s/^ /./' {} \;
    # or stripping ./ first
    find . -type f -name '*.avi' -execdir rename 's|^\./||; s/\.(?=[^.]*\.)/ /g' {} \;
    

    -execdirPOSIX 解决方案在不可用时需要运行 shell进行模拟。可能的方法:

    find . -type f -name '*.avi' -exec sh -c '
       cd "$(dirname "$2")" && rename "$1" "$(basename "$2")"
    ' find-sh 's/\.(?=[^.]*\.)/ /g' {} \;
    

    笔记:

    • rename本身不是一个 POSIX 工具;
    • 我选择将其s/\.(?=[^.]*\.)/ /g作为单独的参数传递,sh而不是将其嵌入到单引号的 shell 代码中并担心正确嵌套引号。
  • 改进您的表达式,使其不改变目录组件(包括前导点),只改变文件名(/路径名中最后一个字符串之后的字符串)。我对正则表达式的了解不够好,无法帮助您解决这个问题。

答案2

您的目录或文件名中是否有空格?这可能会导致命令-exec构建失败并传递给 shell。

尝试在括号周围添加引号,这样任何带有空格的文件名就不会被 shell 视为单独的参数:

find . -type f -name '*.avi' -exec  rename   's/\.(?=[^.]*\.)/ /g' "{}" \;

相关内容