Каков наилучший способ использования подстановочных знаков в 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и ожидаю получить ошибку "cannot move". Это безвредно, и другие файлы и каталоги будут перемещены, как и ожидалось.

Статус завершения команды будет ненулевым, что будет означать ошибку, но поскольку от него ничего не зависит, его можно проигнорировать.


В этом случае другие имена содержат тире перед tut:

mv *-tut* tutorials

Или, если у вас есть подобные вещи, python_tutкоторые вы хотите переместить, также разрешите подчеркивание:

mv *[_-]tut* tutorials

Или, чтобы потребовать любой дополнительный символ перед подстрокой tut(которого tutorialsнет),

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'

Просто проигнорируйте ошибку.

Нет, правда. Вы знаете, что получите ошибку, так как шаблон glob совпадает с целью. Вы также знаете, что это ничего не значит, так как система не может переместить каталог внутрь себя, и она достаточно умна, чтобы понять это до того, как испортить вашу файловую систему.

решение4

Самый простой способ — переименовать целевой каталог tutorials/во что-то другое, не соответствующее расширению имени файла, и переименовать его по своему усмотрению после выполнения перемещения.

Связанный контент