Bash

遞歸重命名排除目前目錄

  • February 10, 2020

我使用這個命令遞歸地重命名文件:

find -iname \*.bak | rename 's/.bak/.old/'

但我想排除目前目錄。例子:

.bak
dir1/.bak
dir2/.bak
...

在我想要這個之後:

.bak
dir1/.old
dir2/.old
...

試試這個

find -iname \*.bak -not -path "./.bak" | rename 's/.bak/.old/'

使用find支持-mindepth謂詞的 a:

find . -mindepth 2 -type f -name '*.bak' | rename 's/\.bak$/.old/'

-mindepth謂詞允許您定義可以進行匹配的最小搜尋深度。深度 0 是根搜尋路徑本身(.),深度 1 是根搜尋路徑下方的任何內容(例如./somename),深度 2 是其下方的任何內容(例如./somename/other),等等。

請注意,-iname不需要不區分大小寫的匹配,因為無論如何您rename都不會重命名具有其他類型的文件名後綴大寫的文件,因此我已將其更改為-name測試。我還修復了您的rename呼叫,以便bak名稱中其他位置帶有字元串的文件(例如 )rebak.bak不會以奇怪的方式重命名(例如 into r.old.bak)。

我還添加-type f了只find考慮正常文件,即不考慮目錄等。

對於更便攜的解決方案:

find . -mindepth 2 -type f -name '*.bak' -exec sh -c '
   for pathname do
       mv "$pathname" "${pathname%.bak}.old"
   done' sh {} +

這不依賴於rename實用程序。

find . -mindepth 2 -type f -name '*.bak' -exec rename 's/\.bak$/.old/' {} +

rename直接從find.

有關的:


使用bash,您可以完全跳過find,而是執行

shopt -s globstar dotglob

rename 's/\.bak$/.old/' ./*/**/*.bak

**globbing 模式匹配任意數量的中間子目錄。globstar使用shell 選項啟用此特殊模式。初始./*/確保我們只查看目前目錄的子目錄,而不是目前目錄本身。

dotglobshell 選項確保我們將隱藏名稱與模式匹配。

但是,上述內容不會專門挑選正常文件(但您的find命令也不會)。為此,請使用循環:

shopt -s globstar dotglob

for pathname in ./*/**/*.bak; do
   [[ ! -f $pathname ]] && continue
   rename 's/\.bak$/.old/' "$pathname"
done

這也會將符號連結重命名為正常文件。

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