10 сентября 2021

Учим утилиту cp (копирование папок/файлов) делать то, что она делать не умеет - создавать директории/каталоги/папки при копировании

Любой, даже начинающий линуксятник, как правило знаком со многими штатными, консольными утилитами Linux.
Не исключение и консольная утлилита - cp, которая позволяет в консоли/терминале производить копирование файлов и папок из одной директории/каталога в любую другую.
В этой статье мы с Вами научимся научить её делать то, что она изначально делать просто не умеет, а именно создавать новые директории/каталоги/папки/файлы при рекурсивном копировании.
И в результате мы с вами получим удобный инструмент - 2 (два) в одном - утилиты mkdir и cp, что весьма улучшит функционал утилиты cp.


Т.к. утилита cp консольная, то для работы с ней нам понадобится, естественно Терминал (Ctrl+Alt+T).

Открываем его и, для эксперимента, давайте попробуем выполнить копирование содержимого какой-либо папки или самой папки, например содержимое папки: applications
из .local/share/ - Домашняя папка (/home)
Полный путь:
.local/share/applications/ или ~/.local/share/applications/
например в каталог Документы и пропишем при копировании создание в нём новой папки Проба и подпапки в ней 14, куда будет скопировано содержимое папки applications и посмотрим, что у нас в результате получится.

Вводим в Терминале (Ctrl+Alt+T) следующий код и жмём на Ентер на клавиатуре:
cp -R .local/share/applications/* Документы/Проба/14
или
cp -R ~/.local/share/applications/* ~/Документы/Проба/14
И в результате мы получаем ошибку:
показывающую и кричащую нам, как раз о том, что утилита cp не умеет создавать при копировании новые директории/каталоги/папки, а значит у нас нет другого выхода, как сначала воспользоваться консольной утилитой по созданию новых директорий/каталогов/папок:
- mkdir
- или в Графическом режиме (GUI) в вашем файловом менеджере (ФМ) и только после этого копировать содержимое папки applications в заранее созданные в каталоге Документы новые папку Проба и подпапку в ней 14!

Не очень удобно, правда ведь?!
Что же делать?!
Как же всё таки нам сделать, чтобы она (утилита cp) всё же могла выполнить нашу задачу?

На самом деле, всё очень просто!
Нам всего лишь надо добавить в файл .bashrc (можно в самый его конец, с новой строки) в Домашней папке (/home) следующий код/функцию, обязательно сохраняя отступы, как в нём:
    mkcp() {
        test -d "${@: -1}" || mkdir -p "${@: -1}"
        cp "$@"
    }
Но такай код/функция будет работать только при копировании в пределах Домашнего каталога (/home).
Поэтому, если вы планируете копировать что-либо с созданием каталогов/папок не только в пределах Домашнего каталога (/home), а и в системной директории / (например в /opt/), то тогда уже нужен другой код/функция:
    mkcp() {
        test -d "${@: -1}" || sudo mkdir -p "${@: -1}"
        sudo cp "$@"
    }
Но при её выполнении нужно уже будет вводить свой пароль Пользователя.

Cделать это можно и в Терминале (Ctrl+Alt+T) с помощью того же консольного редактора nano, выполнив команду:
(напоминаю, после внесения изменений в файл в редакторе nano, для сохранения изменений жмёте на клавиатуре на Ctrl+O (буква O)+Enter и на Ctrl+X для выхода в консоль/терминал)
nano .bashrc
или
nano ~/.bashrc

Выглядеть это должно так:
и активировать этот файл .bashrc в данной сессии консоли/терминала командой:
(если этого не сделать, то введёный код/функция работать не будет, а только после закрытия консоли/терминала и заново её/его запуска, что в данном случае не очень удобно)
. .bashrc
или
. ~/.bashrc

Ну, и, для ленивых, сделать всё это одной командой в Терминале (Ctrl+Alt+T):
echo -e 'mkcp() {\n    test -d "${@: -1}" || mkdir -p "${@: -1}"\n    cp "$@"\n}' >> .bashrc; . .bashrc
или
echo -e 'mkcp() {\n    test -d "${@: -1}" || mkdir -p "${@: -1}"\n    cp "$@"\n}' >> ~/.bashrc; . ~/.bashrc
Если с созданием каталогов/папок в системной директории / (например в /opt/), то:
echo -e 'mkcp() {\n    test -d "${@: -1}" || sudo mkdir -p "${@: -1}"\n    sudo cp "$@"\n}' >> .bashrc; . .bashrc
или
echo -e 'mkcp() {\n    test -d "${@: -1}" || sudo mkdir -p "${@: -1}"\n    sudo cp "$@"\n}' >> ~/.bashrc; . ~/.bashrc

Давайте вкратце, чтобы простому пользователю было понятно, мы с вами разберём, что же мы в этом коде/функции такого понаписали?

А написали мы с вами фактически "новую" утилиту!
И "назвали" мы её - mkcp.
Вернее, мы с вами объединили вместе 2 (две) утилиты - mkdir и cp.

Ну, и теперь давайте снова выполним в Терминале (Ctrl+Alt+T) копирование, но только вместо cp мы с вами в коде напишем - mkcp, т.е. то, что мы с вами "создали", в результате чего, мы с вами видим, что всё прошло успешно, без каких-либо ошибок:
mkcp -R .local/share/applications/* Документы/Проба/14
или
mkcp -R ~/.local/share/applications/* ~/Документы/Проба/14
Чтобы убедиться, что всё прошло на УРА, давайте проверим, действительно ли всё отработало и в каталоге Документы создались новые папка Проба и подпапка в ней 14 поочерди командами ls:
ls Документы
ls Документы/Проба
ls Документы/Проба/14
в результате чего мы получим выводы, подтверждающих, что всё создалось и всё скопировалось:
То же самое мы видим и в Графическом режиме (GUI) в вашем файловом менеджере (ФМ):
Для сравнения, чтобы убедиться, что мы скопировали в созданные нами при копировании папки именно то, что мы хотели, сделаем вывод ls .local/share/applications/ командой в Терминале (Ctrl+Alt+T):
ls .local/share/applications
или
ls ~/.local/share/applications
где видим, что все файлы и папки из это директории соответствуют всем файлам и папкам в созданной нами при копировании папке 14 - полный путь: Документы/Проба/14

Те же папки и файлы и в Графическом режиме (GUI) в нашем файловом менеджере (ФМ):
А значит, мы с вами всё сделали правильно и всё работает должным образом!

Всем приятного юзанья и всяческих благ!

P.S. Если у вас появились вопросы или мнения по данной статье, обсудить их можно на нашем форуме:

8 комментариев :

  1. У меня почему-то не взлетело(

    ОтветитьУдалить
    Ответы
    1. Проверял много раз, всё работает на ура.

      Ошибки не выкидывало в процессе?

      Удалить
    2. cp -R foo.jpg ~./mkcp/bnm/
      cp: невозможно создать обычный файл '~./mkcp/bnm/': Нет такого файла или каталога
      это уже после редактирования и перезапуска башрц

      Удалить
    3. agafron, попробуйте использовать MKCP вместо CP

      Удалить
    4. Прошу прощения, друзья!
      Мой косяк...
      polmozga абсолютно правильно подметил - команда должна начинаться с mkcp, а не с cp!!!
      Я по недосмотру в статье указал cp, вот и не работало, хотя в скрине Терминала команда mkcp.
      Поправил, поменял cp на mkcp, как и должно быть, всё арбайтен!

      Удалить
  2. Обезтянка!!! А кому это НАДО???

    ОтветитьУдалить
  3. Спасибо за очень полезную информацию!

    ОтветитьУдалить