在 bash 脚本中获取祖父目录 - 为路径中的目录重命名文件
Posted
技术标签:
【中文标题】在 bash 脚本中获取祖父目录 - 为路径中的目录重命名文件【英文标题】:Get grandparent directory in bash script - rename files for a directory in their paths 【发布时间】:2014-02-11 18:49:50 【问题描述】:我有以下脚本,当我得到一堆需要重命名为包含它们的目录名称的文件时,我通常会使用它。
现在的问题是我需要将文件重命名为上两级的目录。我怎样才能得到祖父母目录来完成这项工作?
使用以下内容,我会收到类似此示例的错误:
“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 .
【问题讨论】:
使用两个句点 (..
) 向上一个目录,所以../../
是祖父目录。
【参考方案1】:
另一种方法是使用
(cd ../../; pwd)
如果在任何***路径(例如/
、/usr/
或/usr/share/
)中执行此操作,您将获得/
的有效目录,但当您深入一层时,您将开始查看结果:/usr/share/man/
将返回 /usr
,/my/super/deep/path/is/awesome/
将返回 /my/super/deep/path
,依此类推。
您也可以将其存储在变量中:
GRANDDADDY="$(cd ../../; pwd)"
然后将其用于脚本的其余部分。
【讨论】:
【参考方案2】:假设文件路径不以/
结尾,如果你使用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】:注意:
* 此答案解决了 OP 的特定问题,在其上下文中,“祖父目录”是指:包含文件的目录的 父 目录(它是从 文件的 角度来看的祖父路径)。
* 相比之下,鉴于问题的通用 title,此处的其他答案(仅)侧重于获取 目录的 祖父母目录; generic 问题的简洁答案是: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 parameter expansion,它返回输入文件名的后缀(扩展名)。
注意 - 手头的文件名 - 如何作为第二个 参数传递给命令以绑定到
$1
,因为bash -c
使用第一个设置$0
(这里设置为虚拟值_
)。
请注意,每个文件只是重命名,即保留在其原始目录中。
警告:
每个具有匹配文件的目录应该只包含 1 个匹配文件,否则多个文件将按顺序重命名为相同的目标名称 - 实际上,只有最后一个重命名的文件将继续存在。【讨论】:
【参考方案4】:你不能使用 realpath ../../
或 readlink -f ../../
吗?请参阅this、readlink(1)、realpath(3)、canonicalize_file_name(3) 和 realpath(1)。您可能想在 Debian 或 Ubuntu 上安装 realpath
软件包。可能 CentOS 有一个等效的软件包。 (readlink
应该始终可用,它在GNU coreutils 中)
【讨论】:
以上是关于在 bash 脚本中获取祖父目录 - 为路径中的目录重命名文件的主要内容,如果未能解决你的问题,请参考以下文章
如何将文件路径作为 bash 脚本中的参数传递给函数? [复制]