Bash

使用 ’ 和 * 移動文件導致錯誤

  • August 22, 2020

我在 bash 腳本中移動文件時遇到問題。我一直在嘗試在同一問題上找到的不同解決方案,但找不到任何有效的解決方案。

我的最後一次嘗試是添加shopt -s dotglob nullglob,但這並沒有解決任何問題..

在本次測試中,

jdir0="/media/sf_Mediaserver3/test22/abbamax.(6th.copy)..kansas.(1999)"


mv -v "$jdir0/*" "$jdir0/subs/" &>> $debuglog

..我得到:

mv: cannot stat '/media/sf_Mediaserver3/test22/abbamax.(6th.copy)..kansas.(1999)/*': No such file or directory

但是,是的,有!

drwxrwx--- 1 root vboxsf   4096 Aug 22 07:06  ../
-rwxrwx--- 1 root vboxsf      0 Aug 21 17:19 'kallee.(222)..nnn.srt'*
-rwxrwx--- 1 root vboxsf 159363 Aug 21 17:26 'movie.test(2929).ismim.mp4'*
drwxrwx--- 1 root vboxsf      0 Aug 22 07:06  subs/

(名字真的很奇怪的原因是我在這個函式之前正在測試刪除無效字元)

更新:顯然我遇到了間歇性錯誤,幾天后我終於將其追溯到伺服器問題(儲存文件的位置)。顯然,如果伺服器沒有完成保存/名稱更改,並且腳本要求它做一些新的事情,就會發生這些錯誤。例如將文件A重命名為B,然後在伺服器執行第一個請求之前要求它將B重命名為C,導致伺服器說:B不存在,這當然會導致錯誤程式碼。

*是 shell 的 glob 運算符。它需要不加引號才能被辨識。引用時,/media/sf_Mediaserver3/test22/abbamax.(6th.copy)..kansas.(1999)/*按字面意思傳遞給mvmv嘗試移動名為 的文件*,但沒有這樣的文件。

所以你需要:

mv -v -- "$jdir0"/* "$jdir0/subs/" >> "$debuglog" 2>&1

"$jdir0"/*呼叫mv.

希望nullglob在這裡,因為這意味著在沒有與該"$jdir0"/*模式匹配的文件的情況下,mv將使用 just 呼叫-v--media/sf_Mediaserver3/test22/abbamax.(6th.copy)..kansas.(1999)/subs/通過mv.

failglob在這種情況下,當 glob 不匹配時中止命令可能是一個更好的選擇,但請注意,bash在這種情況下會以不一致的方式中止,具體取決於呼叫命令的上下文,這使得該選項在腳本中使用起來很棘手。

dotglob是允許 glob 匹配隱藏文件。

現在,請注意 glob 匹配文件,無論它們的類型是什麼¹,所以*上面也將匹配subs. 如果subs是一個目錄的符號連結,mv會很樂意將該subs符號連結移動到該目錄中,導致所有後續移動都失敗,因為subs目標目錄現在已經消失了。如果subs是一個普通的子目錄,mv可能會抱怨它無法將目錄移動到自身中。

所以你可能想寫它:

shopt -s extglob
mv -v -- "$jdir0"/!(subs) "$jdir0/subs/" >> "$debuglog" 2>&1

!(pattern)與任何匹配的文件名匹配的 ksh 擴展 glob 運算符在哪裡pattern,所以這裡移動任何文件,但subs.

另請注意,在bashshell 中,即使在非互動式 shell 實例中,在重定向目標中也需要引用參數擴展(bash 處於 POSIX 模式時除外)。


¹ 除非您使用 zsh 而不是 bash 及其 glob 限定符,例如*(.)僅移動正常文件

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