Zsh

zsh:如果子文件夾中的文件具有相同的名稱,則重命名文件

  • October 31, 2021

有以下文件結構:

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.waldoanother-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 文件。
  • 如果沒有共享基本名稱的文件,它應該忽略並繼續下一個,直到找到匹配項。
  • 文件名是正常的作業系統文件名,所以是的,可能有 &()$$ $$# 等存在。

這可能是這樣的:

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: root 名稱(不帶副檔名的部分,如 csh/vim…)
  • $var:h: head (目錄名,如 csh/vim)
  • (N): Nullglob glob qualifier: 所以如果沒有匹配就不會報錯:
  • (Y1): 在第一場比賽 glob 限定符之後停止。

引用自:https://unix.stackexchange.com/questions/675575