當來源和目標相似時,在 bash 中使用通配符擴展的最佳方法是什麼?

當來源和目標相似時,在 bash 中使用通配符擴展的最佳方法是什麼?

假設我有這些資料夾:

$ ls
css-tricks/ django-tutorial/ good-tuts.txt js-tut/ tutorials/ tuts.txt

其中一些tut在他們的名字中。我想將tut名稱中包含的所有文件/資料夾移動到資料夾中tutorials/。如果我執行命令

$ mv *tut* tutorials/

我收到以下訊息:

mv: cannot move 'tutorials' to a subdirectory of itself, 'tutorials/tutorials'

我該怎麼做才能避免這種情況發生?


我能想到的技巧之一是將目標資料夾暫時重命名為其他名稱,並在命令執行後將其更改回所需的名稱。然而,我希望知道一個更優雅的解決方案。

答案1

就我個人而言,在我要以互動方式發出命令的情況下,我只會這樣做mv *tut* tutorials並期望得到“無法移動”錯誤。這是無害的,其他文件和目錄將按預期移動。

該命令的退出狀態將不為零,表示錯誤,但由於沒有任何東西依賴它,因此它可能會被忽略。


在這種情況下,其他名稱前麵包含破折號tut

mv *-tut* tutorials

或者,如果您還想移動類似的內容python_tut,也可以使用底線:

mv *[_-]tut* tutorials

或者,要在子字串之前需要任何額外字元tuttutorials沒有),

mv *?tut* tutorials

透過更多的打字和思考,在以下位置使用擴展的通配模式bash

shopt -s extglob
mv *tut!(orials*) tutorials

第二個變體將匹配包含子字串但tut後面不緊跟字串的任何內容orials。該模式將不匹配tutorials並且也會跳過tutorials1等。

答案2

您也可以使用find

find . -type d -name "*tut*" -not -path "./tutorials" -exec mv -t "tutorials" {} +

答案3

我收到以下訊息:

mv: cannot move 'tutorials' to a subdirectory of itself, 'tutorials/tutorials'

只需忽略該錯誤即可。

不完全是。您知道您會收到錯誤,因為全域模式與目標相符。您也知道這沒有任何意義,因為系統無法在其內部移動目錄,而且它足夠聰明,可以在弄亂您的檔案系統之前意識到這一點。

答案4

最簡單的方法是將目標目錄重新命名tutorials/為檔案名稱擴充功能中不匹配的其他內容,並在執行移動後將其重命名為您想要的名稱。

相關內容