当源和目标相似时,在 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/为与文件名扩展不匹配的其他目录,并在执行移动后将其重命名为您想要的名称。

相关内容