Bash
遞歸重命名排除目前目錄
我使用這個命令遞歸地重命名文件:
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
不會以奇怪的方式重命名(例如 intor.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 選項啟用此特殊模式。初始./*/
確保我們只查看目前目錄的子目錄,而不是目前目錄本身。
dotglob
shell 選項確保我們將隱藏名稱與模式匹配。但是,上述內容不會專門挑選正常文件(但您的
find
命令也不會)。為此,請使用循環:shopt -s globstar dotglob for pathname in ./*/**/*.bak; do [[ ! -f $pathname ]] && continue rename 's/\.bak$/.old/' "$pathname" done
這也會將符號連結重命名為正常文件。