在bash脚本中获取祖父目录 - 为其路径中的目录重命名文件

时间:2014-01-21 22:43:25

标签: linux bash path centos batch-rename

我有以下脚本,当我得到一堆需要重命名为包含它们的目录名的文件时,我通常会使用这个脚本。

现在的问题是我需要将文件重命名为两级以上的目录。如何获取祖父目录以使其工作?

使用以下内容我会收到类似此示例的错误: “mv:无法将./48711/zoom/zoom.jpg移动到./48711/zoom/./48711/zoom.jpg:没有这样的文件或目录”。这是在CentOS 5.6上运行的。

我想要命名最终文件:48711.jpg

#!/bin/bash

function dirnametofilename() {
  for f in $*; do
    bn=$(basename "$f")
    ext="${bn##*.}"
    filepath=$(dirname "$f")
    dirname=$(basename "$filepath")
    mv "$f" "$filepath/$dirname.$ext"
  done
}

export -f dirnametofilename

find . -name "*.jpg" -exec bash -c 'dirnametofilename "{}"'  \;

find .

4 个答案:

答案 0 :(得分:7)

另一种方法可能是使用

(cd ../../; pwd)

如果在//usr//usr/share/等任何顶级路径中执行此操作,您将获得/的有效目录,但是当您深入了解一级,您会看到结果:/usr/share/man/会返回/usr/my/super/deep/path/is/awesome/会返回/my/super/deep/path,依此类推。

您也可以将其存储在变量中:

GRANDDADDY="$(cd ../../; pwd)"

然后将其用于脚本的其余部分。

答案 1 :(得分:3)

注意:
* 此答案解决了OP的特定问题,在其上下文中“祖父目录”表示:包含文件的目录的目录(它是文件的视角中的祖父母路径 *相比之下,鉴于问题的通用标题,此处的其他答案仅关注(仅)获取目录的祖父目录; 通用问题的简洁答案是grandParentDir=$(cd ../..; printf %s "$PWD")以获取完整路径,而grandParentDirName=$(cd ../..; basename -- "$PWD")来获取目录。只是名字。 功能

尝试以下方法:

find . -name '*.jpg' \
  -execdir bash -c \
   'old="$1"; new="$(cd ..; basename -- "$PWD").${old##*.}"; echo mv "$old" "$new"' - {} \;

注意:echo前置mv是安全的 - 删除它以执行实际的重命名。 功能

  • -execdir ..\;在包含给定匹配文件的特定目录中执行指定的命令,并将{}扩展为每个文件的文件名。

  • bash -c用于执行小型临时脚本:

    • $(cd ..; basename -- "$PWD")确定包含该文件的目录的目录名,该文件是来自文件的 grandparent 路径 perspective。

    • ${old##*.}是一个Bash parameter expansion,它返回输入文件名的后缀(扩展名)。

    • 注意{} - 手头的文件名 - 如何作为 2nd 参数传递给命令,以便绑定到$1,因为{{1使用第一个设置bash -c(此处设置为虚拟值$0)。

  • 请注意,每个文件仅重命名,即保留在其原始目录

<强>买者

  • 具有匹配文件的每个目录应仅包含 1 匹配文件,否则将按顺序将多个文件重命名为相同的目标名称 - 实际上,只有最后重命名的文件才能生存。

答案 2 :(得分:1)

假设文件路径未在/中结束,如果您使用dirname则不应该这样做,您可以

Parent = "${filepath%/*}"
Grandparent = "${filepath%/*/*}"

所以做这样的事情

[[ "${filepath%/*/*}" == "" ]] && echo "Path isn't long enough" || echo "${filepath%/*/*}"

如果您使用相对路径(例如find .),这也可能无效。在这种情况下,您将需要使用

filepath=$(dirname "$f")
filepath=$(readlink -f "$filepath")

而不是

filepath=$(dirname "$f")

此外,您永远不会剥离扩展程序,因此没有理由从文件中获取它,然后再次附加它。

答案 3 :(得分:1)

你不能使用realpath ../../readlink -f ../../吗?请参阅thisreadlink(1)realpath(3)canonicalize_file_name(3)realpath(1)。您可能希望在Debian或Ubuntu上安装realpath包。可能CentOS有一个相同的包。 (readlink应始终可用,位于GNU coreutils