如何讓這個查找和重命名命令與子目錄一起使用?
可能重複:
我有一個很大的音樂文件目錄,隨著文件和目錄的來來去去,這些文件經常發生變化。我的偏好是確保文件和目錄名稱中沒有空格,因此我將它們全部替換為下劃線。
我進入主目錄並執行以下命令:
$ find -type d -exec rename 'y/\ /\_/' {} \;
問題是當有子目錄時,這個命令似乎會失去並且會返回錯誤。所以如果我有以下目錄結構:
…如果我執行命令,我會收到以下錯誤:
$ find -type d -exec rename 'y/\ /\_/' {} \; find: `./Test 02': No such file or directory find: `./Test 01': No such file or directory find: `./Test 03': No such file or directory
然後結果是我的目錄結構看起來像這樣。請注意,子目錄中仍然有空格:
如果我再次執行該命令,我會收到這些錯誤,即使它似乎重命名了相關目錄:
$ find -type d -exec rename 'y/\ /\_/' {} \; find: `./Test_01/Test A': No such file or directory find: `./Test_01/Test C': No such file or directory find: `./Test_01/Test B': No such file or directory
最後,我再次執行該命令,沒有收到任何錯誤,並且所有目錄和子目錄都按我想要的方式命名:
顯然,當我有多個子目錄時,這需要執行命令更多次,這可能會變得乏味。
我怎樣才能使這個命令只需要執行一次,它會一次性重命名所有目錄和子目錄?
我的最終目標是將它包含在 Bash 腳本中,以便我可以將它與其他類似的管家命令一起執行,因此我需要它不返回錯誤或需要我提供更多輸入。另外,如果這有所不同,我正在執行 Ubuntu 12.04。
這是發生的事情:
find
找到匹配的目錄./Test 02
。find
在該目錄上執行rename
命令。rename
重命名Test 02
為Test_02
.find
試圖進入目錄Test 02
。但它不再存在。解決此問題的最簡單方法是告訴
find
以相反的方式工作:首先在目錄中查找匹配項,然後檢查目錄本身是否匹配。這就是-depth
選項的作用。如果你只添加
-depth
,你會遇到另一個問題,那就是當find
到達時Test 01/Test A
,它會呼叫rename 'y/\ /\_/' 'Test 01/Test A'
,它會嘗試將該目錄重命名為Test_01/Test_A
. 這將失敗,因為沒有名為Test_01
. 一個簡單的解決方法是使用該-execdir
選項,該選項rename
在目錄內部呼叫並作為參數Test 01
傳遞。您可以通過在一批中Test A
傳遞多個參數來加快速度,使用而不是終止命令。rename``+``;``-execdir
find -depth -name '* *' -type d -execdir rename 'y/ /_/' {} +
或者,使用這個簡短但神秘的 zsh 命令:
autoload zmv zmv -Qw '**/*(/D)' '$1${2// /_}'
該
zmv
函式根據模式重命名文件。源模式是,它以遞歸方式**/*
匹配所有子目錄中的所有文件 ( ) ( )。glob 限定符(由選項啟動)表示僅匹配目錄 ( ) 並且包含點文件 ( )。該選項為源模式中的每個萬用字元創建一個反向引用。替換以which 指定第一個萬用字元的匹配開始(對於,這包括一個 final ),然後是,它(匹配的內容)被修改為用 替換所有空格字元。添加*``**/``-Q``/``D``-w``$1``**``/``${2// /_}``$2``*``_``-v
選項來查看命令的作用,您會注意到它首先遍歷深度,例如find -depth
.