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



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

现在的问题是我需要将文件重命名到两级以上的目录。 如何获取祖父目录来执行此操作?

在下面,我收到类似此示例的错误: "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 .

另一种方法是使用

(cd ../../; pwd)

如果这在任何顶级路径(如//usr//usr/share/)中执行,你会得到一个有效的/目录,但是当你更深入一级时,你会开始看到结果:/usr/share/man/会返回/usr/my/super/deep/path/is/awesome/会返回/my/super/deep/path,依此类推。

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

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

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

假设文件路径不以/结尾,如果你使用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")

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

注意:
*这个答案解决了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")确定包含文件的目录的目录名称,从文件的角度来看,这是祖父路径。

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

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

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

注意事项

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

你不能使用realpath ../../readlink -f ../../吗?看到这个,readlink(1),realpath(3),canonicalize_file_name(3)和realpath(1)。您可能希望在 Debian 或 Ubuntu 上安装realpath软件包。可能 CentOS 有一个等效的软件包。(readlink应该始终可用,它在GNU coreutils中)

相关内容

  • 没有找到相关文章