从具有特定扩展名的所有文件中递归删除扩展名

Sco*_*orb 3 bash ubuntu rename mv

我有一个包含一堆子目录的目录,其中包含一堆带有扩展名的文件 .no_sub.

我想将每个带有扩展名的文件重命名.no_sub为相同的名称.no_sub删除。

所以foo.no_sub->foo

我可以在 Bash 中做到这一点吗?(我在 Ubuntu 20.04 上)

Kus*_*nda 14

使用标准findsh以及mv

find . -type f -name '*.no_sub' -exec sh -c '
    for pathname do
        mv -- "$pathname" "${pathname%.no_sub}"
    done' sh {} +
Run Code Online (Sandbox Code Playgroud)

这会.no_sub在当前目录中或当前目录下查找名称以 string 结尾的任何常规文件。对于这些路径名的批次,将调用一个简短的内嵌 shell 脚本。此sh -c脚本遍历给定的一批路径名,并通过删除.no_sub文件名后缀来重命名每个路径名。文件名后缀的删除是使用标准${variable%suffix}参数扩展完成的。

不检查文件名冲突。

这是类似的,以由Marcus穆勒提供的解决方案在单个文件的重命名发生在相同的方式,但使用find生成路径名的方式,将拿起隐名环路的列表,并包含明确的文件类型过滤器仅迭代常规文件。

另请参阅:了解 `find` 的 -exec 选项


由于我们知道内联脚本的每个文件名都以 结尾.no_sub.no_sub如果我们想,我们可以避免在那里重复:

find . -type f -name '*.no_sub' -exec sh -c '
    for pathname do
        mv -- "$pathname" "${pathname%.*}"
    done' sh {} +
Run Code Online (Sandbox Code Playgroud)


Mar*_*ler 13

使用 shell 的强大功能获取所有文件,然后使用常用工具重命名它们

shopt -s nullglob ## as recommended and explained in the comments
shopt -s globstar
shopt -s dotglob
for fname in **/*.no_sub ; do
  mv -- "${fname}" "${fname%.no_sub}"
done
Run Code Online (Sandbox Code Playgroud)

这里,

  • shopt -s globstar**作为递归全局启用
  • shopt -s dotglob 启用查找 .*.no_sub
  • for循环是一个特殊字符安全的方式通过所有文件(永远不要解析ls
  • mv语法mv source target;
  • 我有时会过于小心,但我也喜欢${fname}比仅仅更好的$fname,因为不能有变量名称混淆。它只是扩展到变量的内容fname,即扩展到当前文件
  • 变量扩展${variable%pattern}扩展到变量内容,但被后缀模式减少pattern


lar*_*sks 11

你可以用findand做到这一点xargs

find . -name '*.nosub' -print0 | xargs -0 rename .nosub ""
Run Code Online (Sandbox Code Playgroud)

-print0选项find-0的选择xargs是有正确处理文件名用空格。该rename命令是util-linux包提供的命令。