Как я могу получить mv (или подстановочный знак *) для перемещения скрытых файлов?

Я переношу свой домашний каталог из старой системы в новую, и созданный мной архив содержит все, включая скрытые файлы, такие как .bashrc. Однако, когда я перемещаю содержимое распакованного архива (который находится в /tmp) в мой новый домашний каталог, скрытые файлы не копируются (mv /tmp/home/rcook/* /home/rcook/). Как я могу заставить mv переместить их?

На самом деле, я думаю, что проблема не в mv, а в глобализации bash. Если я сделаю это:

mkdir amkdir btouch a/.footouch a/barmv a/* b/ls -a a/ b/

Я вижу это:

a/:.  ..  .foob/:.  ..  bar

a/.foo не двигался. Итак, как я могу получить подстановочный знак * для поиска скрытых файлов?

Да, я полагаю, я мог бы распаковать архив непосредственно в свой домашний каталог, но архив распаковывается в home/rcook/..., и я хочу быть уверен, что перезапишу новый .bashrc и т.д. со старыми, настроенными версиями и знанием того, как находить и перемещать скрытые файлы, это полезный навык. Предложения?


Некоторые ответы предлагают сделать что-то вроде mv src/.* dest/. Однако я попробовал это в своих тестовых каталогах и получил ошибки. Начиная с:

rcook$ ls -a a/ b/a/:.  ..  bar  .foob/:.  ..rcook$ mv a/.* b/mv: cannot move 'a/.' to 'b/.': Device or resource busymv: cannot remove 'a/..': Is a directoryrcook$ ls -a a/ b/a/:.  ..  barb/:.  ..  .foo

Что я делаю не так?

Вы можете сделать это :

shopt -s dotglobmv /tmp/home/rcook/* /home/rcook/

Вы можете положить

shopt -s dotglob

В вашем ~/.bashrc если вы хотите, чтобы это было значение по умолчанию.

Видеть http://mywiki .wooledge.org/glob


Другой подход к копированию точечных файлов:

mv /tmp/home/rcook/.[!.]* /home/rcook/

Не используйте шаблон ..* поскольку это соответствует .. (указатель на родительский каталог). Если есть файлы, имена которых начинаются с двух точек (..something), также используйте шаблон ..?*.

В ваших дополнениях вы получили ошибки, но код все еще работал. Единственное, что нужно добавить, это то, что вы это рассказали только чтобы скопировать точечные файлы. Попробуй:

mv src/* src/.* dst/

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

~/scratch [andrew] $ mv from/* from/.* to/mv: cannot move ‘from/.’ to ‘to/.’: Device or resource busymv: cannot remove ‘from/..’: Is a directory~/scratch [andrew] $ ls -a from/ to/from/:.  ..to/:.  ..  test  .test

Если ты ls -l в каталоге вы увидите . и .. среди перечисленных файлов. Итак, я думаю mv .* /dest принимает во внимание эти указания. Попробуй:

mv /tmp/home/rcook/{*,.[^.]*,..?*} /home/rcook/

это приведет к игнорированию этих указателей текущего и родительского директорий.

Вы получите сообщение об ошибке, если какой-либо из трех шаблонов *, [^.]* или ..?* не соответствует ни одному файлу, поэтому вы должны включать только те, которые соответствуют.

Я могу придумать два возможных решения. Первый - использовать вместо этого cp с его рекурсивной опцией, копируя текущий каталог в пункт назначения.

cp -Rp . /desired/directory

затем вы можете удалить исходные файлы в текущем каталоге

В качестве альтернативы, если вы знаете, что файлы имеют правильные имена (без пробелов, подстановочных знаков, непечатаемых символов), вы можете сделать что-то вроде этого

mv $(ls -A) /desired/directory

На самом деле в Linux нет такой вещи, как "скрытые" файлы. Файлы, начинающиеся с точки, по умолчанию просто скрыты из списков файлов.

Чтобы копировать файлы даже с помощью глобуса, вам необходимо добавить к файлу префикс с . такие как mv -u .* foo и затем .foo будет отображаться как foo/.foo при перемещении.

Опция -u будет перемещать файлы только в том случае, если источник более новый или пункт назначения отсутствует. Или вы могли бы просто игнорировать ошибки, связанные с перемещением . и .. поскольку они являются специальными файлами и не могут быть перемещены, но попадают в .* шарик у раковины.

Я знаю, что это устарело, но один простой способ сделать это -:

mv a/{.*,*} b/

Объяснение

Это называется расширение скобки. В этом случае оболочка расширяет указанный вами путь, объединяя строку, указанную перед фигурными скобками (в данном случае a/), за которым следует каждый вариант, указанный в списке, заключенный в фигурные скобки.Список вариантов состоит из значений, разделенных запятыми и, опять же, заключенных в фигурные скобки. Итак, в данном случае мы имеем .* и * как элементы, поэтому список должен быть {.*,*}.

mv a/{.*,*} b/

Приведенное выше выражение можно прочитать следующим образом: переместить все файлы, начинающиеся с точки (.*) и что-нибудь еще (*) в a/ каталог к b/ каталог.

Больше подсказок

Это очень полезно и может быть использовано в различных сценариях. Например, представьте, что вам нужно создать 100 файлов со следующим шаблоном именования: file1, file2, file3...файл100. Вы можете легко достичь этого, сделав это

touch file{1..100}

В этом случае вы можете увидеть диапазон было дано. Вы можете сделать это, разделив первое и последнее значения двумя точками (..).

Выход За пределы!

Я новичок в мире Unix и, даже зная, что это работает в bash и zsh (оболочки, которые я использовал до сих пор), я не могу гарантировать, что это будет работать в любой оболочке.

Вы можете узнать больше о расширения один универсализация в документации вашей оболочки (используя: man bash или man zshall, для bash и zsh соответственно).

Надеюсь, это поможет будущим читателям!

Итак, у нас есть:

a|-- .foo`-- bar

и:

b

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

Затем я взял 30 секунд для этой команды:

$ mv --help

Потом я нашел свою любовь:

$ mv a/ b/ -T

Примечание: я даже не понимаю аргумента -T. Он просто сделал то, что мне было нужно. Здесь написано:

-T, --нет-целевого-каталога обрабатывайте DEST как обычный файл

В моем случае я просто пытался mv один скрытый файл, и это было решение:

FILE=.myHiddenFilemv "$FILE" dest/

Объяснение

Сначала я пытался:

mv .myHiddenFile dest/

Но он продолжал выдавать ошибку:

mv: cannot stat '.myHiddenFile': No such file or directory

Даже несмотря на то, что ls -al показал, что файл и dest/ существовавший.

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

Альтернативный способ - использовать (GNU) find:

find /tmp/home/rcook/ -mindepth 1 -maxdepth 1 -exec mv {} /home/rcook/ \;

Если вы хотите скопировать файлы, включая скрытые файлы, в текущий каталог, в котором вы находитесь.

cp -Rp source-directory/. .