有以下文件结构:
charlie
├──this-file.foo.1
├──this-file.foo.2
└──this-file.foo.3
foxtrot
├──another-file.foo.1
├──another-file.foo.2
├──another-file.foo.3.bar
├──another-file.foo.4.baz
└──another-file.foo.5.qux
this-file.waldo
another-file.waldo
我想重命名根文件夹中的所有文件,在本例中this-file.waldo
为another-file.waldo
.如果在任何子文件夹中存在与 .waldo 文件具有相同基本名称的文件,那么我想使用包含同名文件的子文件夹的名称重命名 .waldo 文件,如下所示:
charlie
├──this-file.foo.1
├──this-file.foo.2
└──this-file.foo.3
foxtrot
├──another-file.foo.1
├──another-file.foo.2
├──another-file.foo.3.bar
├──another-file.foo.4.baz
└──another-file.foo.5.qux
charlie.waldo
foxtrot.waldo
当且仅当子文件夹具有共享相同基本名称的文件时,才必须重命名该文件,并且必须使用与子文件夹相同的名称来重命名该文件。
实现这一目标最有效的方法是什么?
- 始终存在 .waldo 文件。
- 如果没有共享基本名称的文件,它应该忽略并继续下一个文件,直到找到匹配项。
- 文件名是正常的操作系统文件名,所以是的,可能存在 &()[]# 等。
答案1
这可能是这样的:
for f (*.waldo(N)) (){ (($#)) && echo mv -- $f $1:h.waldo; } */$f:r.*(NY1)
(echo
如果满意,请删除(空运行))。
那里发现了一些不太常见的 zsh 功能:
for f (values) action
: for 循环的简写形式(类似于 perl 语法)() { body; } args
: 匿名函数$var:r
:r
oot 名称(没有扩展名的部分,如 csh/vim 中...)$var:h
:h
ead (目录名,如 csh/vim 中)(N)
:N
ullglob glob 限定符:所以如果没有匹配,它不会报告错误:(Y1)
:在第一个匹配 glob 限定符后停止。
答案2
首先,您获取当前目录中所有文件的列表
files=(*(.DoN))
然后,你对他们每个人做一些事情:
for file in $files; do
# get the basename
bname="${file%%.*}"
# look for matches in subfolders
typeset -a matches_in_subfolders
matches_in_subfolders=*/${bname}*
# Check whether list of matches is longer than 0
if [ ${#matches_in_subfolders[@]} -gt 0 ] ; then
# do your magic renaming here
fi
done
没有在这里为您重命名,因为我不确定如何处理多个发现,但是
mv -- "${file}" "${matches_in_subfolders[0]}${file#*.}"
将重命名file
为包含它的第一个文件夹的名称及其最长的扩展名(如果不是.waldo
,但是.foo.waldo
,我假设您想要charlie.foo.waldo
,而不仅仅是charlie.waldo
)。