如何在多個目錄中遞歸地將一個文件中的模式重命名為另一個文件
我有幾個目錄,我想通過這些目錄遞歸迭代並更改
.GEOT14246.
到
.GEOT15000.
bash 腳本上是否有一個襯線來執行此操作,或者我是否必須編寫一個帶有 for 循環的腳本。我的嘗試(不起作用)如下:
#!/bin/bash for file in `find . -type f -name "*.GEOT14246.*"` do echo "file = $file" mv $file *.GEOT15000.* done
然後我打電話給:
cd /path/to/script/ sh ./script1.sh /path/to/starting/dir
顯然這不起作用,因為我認為我沒有將起始目錄路徑作為參數傳遞。我對 Unix 很陌生,所以如何向它傳遞參數以說明它應該從哪個目錄開始搜尋以及如何讓腳本工作?
這應該有效:
find . -type f -name "*.GEOT14246.*" -print0 | \ xargs -0 rename 's/GEOT14246/GEOT15000/'
鑑於沒有命名的目錄*
*.GEOT14246.*
*使用 find 的 bash 變體可能類似於:
while IFS= read -r -d $'\0' file; do printf "MV: %-40s => %s\n" "$file" "${file/GEOT14246/GEOT15000}" mv "$file" "${file/GEOT14246/GEOT15000}" done < <(find . -type f -name "*.GEOT14246.*" -print0) | | +--- this is starting directory +--- This ensures no hiccup if newline etc. in name
相對但完整的路徑是從 find 傳遞的——你應該從
printf
語句中看到。新名稱是使用 bash 編譯的:
${some_variable/find/replace}
替換 all
find
的使用:${some_variable//find/replace}
等更多在這裡。這也可能是一個很好的閱讀:BashPitfalls,UsingFind。
閱讀一些指南,例如BashGuide。在網上找到一些教程,但通常不要相信它們,在這里或 irc.freenode.net #bash 上詢問。
您不需要通過呼叫來呼叫腳本
sh
。這也將呼叫 Bourne shell (sh) 而不是 Bourne Again shell (bash)。如果你打算用 bash 執行它;問題bash file
。.sh
擴展也是不合適的。您通常做的是通過以下方式使文件可執行:
chmod +x script_file
然後執行它:
./script_file
shebang負責腳本應該在什麼環境中執行。
在您的腳本中,您不會在任何地方使用傳遞的路徑名。該腳本有一個“參數列表”,從
$0
該列表開始是腳本名稱、$1
第一個參數、$2
第二個參數 - 等等。在您的腳本中,您將朝著以下方向做一些事情:
# Check if argument 1 is a directory, if not exit with error if ! [[ -d "$1" ]]; then printf "Usage: %s [PATH]\n" "$(basename "$0")" >&2 exit 1 fi # OK path="$1" while ... done < <(find "$path" -type f ...)
您目前的
mv
語句會將所有文件移動到您發出命令的任何位置 - 到一個名為*.GEOT14246 的文件。*(如覆蓋每個mv
語句):腳本執行前:
$ tree . └── d1 ├── a1 │ ├── a2 │ │ ├── a3 │ │ │ └── foo.GEOT14246.faa │ │ └── foo.GEOT14246.faa │ └── foo.GEOT14246.faa └── b1 ├── b2 │ ├── b3 │ │ └── foo.GEOT14246.faa │ └── foo.GEOT14246.faa └── foo.GEOT14246.faa
腳本執行後:
$ tree . ├── d1 │ ├── a1 │ │ └── a2 │ │ └── a3 │ └── b1 │ └── b2 │ └── b3 └── *.GEOT15000.*
帶有空格或其他有趣內容的文件/路徑也會使腳本變壞並造成嚴重破壞。因此,您必須引用您的變數(例如
"$file"
)。