重命名目錄 bash 腳本 - 目標…沒有這樣的文件或目錄
我一直在一個簡單的目錄結構上對此進行測試。
我正在嘗試將名稱為“Season”的任何目錄和/或子目錄更改為“Sn”。我到了腳本會改變我想要的東西的地步……除了頂級目錄,如下面的列表所示 - “第 1 季”“第 2 季”“第 3 季”。
目錄結構:
. ├── AnotherShow │ ├── Sn1 │ ├── Sn2 │ ├── Sn3 │ └── Sn4 ├── Movie1 │ ├── Sn1 │ └── Sn2 ├── Movie2 │ ├── Sn1 │ ├── Sn2 │ ├── Sn3 │ └── Sn4 ├── Movie3 │ ├── Sn1 │ └── Sn3 ├── Movie4 │ ├── Sn2 │ └── Sn3 ├── Season 1 ├── Season 2 ├── Season 3 ├── Show │ ├── Sn1 │ ├── Sn2 │ ├── Sn3 │ ├── Sn4 │ └── Sn5 └── TV ├── Sn1 ├── Sn2 ├── Sn3 └── Sn4
我的腳本是:
array="$(find . -maxdepth 2 -type d -iname 'Season*' -print)"; # A more refined way to search for Seasons in a directory. for dir in "${array[@]}"; do # Put this list into an array. Surround the array with quotes to keep all space s (if any) together. new="$(echo "$dir" | sed -e 's/Season 0/Sn/' -e 's/Season /Sn/')"; # Only change Season 0 to SN. Leave othe rs alone. sudo mv -v "$dir" "$new" && echo Changed "$dir" to "$new"; done
問題是您不是在創建數組,而是在創建字元串。您可以通過嘗試列印數組的第一個元素來輕鬆測試:
$ array="$(find . -maxdepth 2 -type d -iname 'Season*' -print)"; $ echo $array ./Season 3 ./Season 1 ./Season 2
看起來不錯吧?但如果那是一個數組,您將能夠分別列印每個元素。不幸的是,上面是一個簡單的字元串1而不是一個數組:
$ echo ${array[0]} ./Season 3 ./Season 1 ./Season 2 $ echo ${array[1]}
該數組實際上由一個字元串組成,這就是“數組” (
${array[1]}
) 的第二個元素為空的原因。在任何情況下,您都不需要數組,只需通讀find
(您也不需要#!/usr/bin/env bash find . -maxdepth 2 -type d -iname 'Season*' | sort -r | while IFS= read -r dir do mv "$dir" ${dir/Season /Sn} && echo Changed "$dir" to "$dir/Season /Sn}"; done
那裡使用了一些技巧。首先,
while
循環遍歷結果find
。for
這與您使用的循環的基本原理相同,但read
可以從標準輸入中讀取。
IFS=
需要避免在空格上拆分(沒有它,目錄將Season 1
被拆分為Season
and1
)。
-r
of read 告訴它不允許反斜杠轉義字元(像\t
和被字面處理的東西\n
),這確保它可以處理即使是最奇怪的名字。是必需的
sort -r
,以便如果您有一個與另一個匹配目錄中的模式匹配的目錄,則子目錄列在父目錄之前。例如:./Season 12/Season 13 ./Season 12
這可確保您在執行
mv "Season 12" "Sn12"
後執行mv "Season 12"/"Season 13" "Season 12"/"Sn13"
。如果你不這樣做,第二個命令將失敗,因為Season 12
不再存在。最後,我刪除了
sudo
. 您應該改為將腳本作為sudo script.sh
.sudo
在腳本中進行隨機呼叫絕不是一個好主意。1我不確定細節,但顯然,bash 將字元串變數視為一個元素的數組。