我有以下脚本,当我得到一堆需要重命名为包含它们的目录名称的文件时,我通常会使用它。
现在的问题是我需要将文件重命名到两级以上的目录。 如何获取祖父目录来执行此操作?
在下面,我收到类似此示例的错误: "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中)