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

134

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

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

mkdir a
mkdir b
touch a/.foo
touch a/bar
mv a/* b/
ls -a a/ b/

Я вижу это:

a/:
.  ..  .foo

b/:
.  ..  bar

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

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


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

rcook$ ls -a a/ b/
a/:
.  ..  bar  .foo

b/:
.  ..
rcook$ mv a/.* b/
mv: cannot move 'a/.' to 'b/.': Device or resource busy
mv: cannot remove 'a/..': Is a directory
rcook$ ls -a a/ b/
a/:
.  ..  bar

b/:
.  ..  .foo

Что я делаю неправильно?

Рэндалл Кук
источник

Ответы:

147

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

shopt -s dotglob
mv /tmp/home/rcook/* /home/rcook/

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

shopt -s dotglob

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

Смотрите http://mywiki.wooledge.org/glob


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

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

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

Жиль Квено
источник
Пожалуйста, ознакомьтесь с дополнениями, которые я поместил внизу моего вопроса. Благодарю.
Рэндалл Кук
1
Ничего плохого, .и ..это специальные каталоги: соответственно текущий каталог и родительский каталог . Это просто предупреждение. Лучше использовать shopt -s dotglobрешение
Gilles Quenot
Я закончил тем, что сделал два хода: mv home/rcook/* /home/rcook/затем mv home/rcook/.* /home/rcook/. Это сработало, хотя хотелось бы перейти по ссылке и сначала прочитать о режиме dotglob. Это спасло бы меня на шаг. +1
Рэндалл Кук
Таким образом, второй подход требует использования абсолютных путей?
franzlorenzon
3
Если вы используете zsh, вы можете использовать в Dподстановку спецификатора или в GLOB_DOTSопции оболочки .
mgalgs
43

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

mv src/* src/.* dst/

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

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

to/:
.  ..  test  .test
Эндрю Шварц
источник
1
Хорошие моменты, @AndrewSchwartz. Мне тоже нравится такой подход. Я думаю, что это заслуживает большего признания.
Рэндалл Кук
Мне больше нравится @Drake Clarris, потому что я работаю в Amazon AWS CodeBuild, и ненулевой код возврата фактически остановил мою сборку. Однако я .hiddenрешил переместить один файл, который у меня был явно, чтобы решить мою проблему.
HeyWatchThis
Если ненулевой код выхода является проблемой, вы можете устранить его, например, добавив || :( ||означает выполнить следующее при false / error, :команда noop). Но это также подавляет допустимые ошибки, например, папка назначения не существует. Я не могу найти более изящный способ , используя mvчтобы исключить .и ..запись. Большой плюс для меня по сравнению с cp - это не запись новых файлов на диск.
Эндрю Шварц
10

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

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

это будет игнорировать эти текущие и родительские указатели dir.

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

Азамат
источник
Приятно. Подобный ответ для этого стиля globbing здесь: superuser.com/a/784046/144977 . Спасибо за публикацию этого.
phyatt
7

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

cp -Rp . /desired/directory

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

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

mv $(ls -A) /desired/directory
Дрейк Кларрис
источник
4
Копирование-затем-удаление сильно отличается от перемещения, если источник и цель находятся в одной файловой системе. По крайней мере, включите опцию -pсохранения метаданных. Использование lsдолжно быть последним средством, и здесь есть лучшие, более простые способы.
Жиль
2

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

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

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

Добей
источник
Пожалуйста, ознакомьтесь с дополнениями, которые я поместил внизу моего вопроса. Благодарю.
Рэндалл Кук
0

Итак, мы имеем:

a
|-- .foo
`-- bar

а также:

b

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

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

$ mv --help

Тогда я нашел свою любовь:

$ mv a/ b/ -T

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

-T, --no-target-directory обрабатывать DEST как обычный файл

user433901
источник
1
Если вы пропустите косые черты, вам не нужно -T. В любом случае это, по сути, говорит mv переместить сам каталог, а не перемещать все файлы из него.
Томасрутер
@thomasrutter, не перемещает ли сам каталог то же самое, что переименовывает его?
Рэндалл Кук
3
Да, если родительский пункт назначения остается тем же самым, это просто переименовывает его. Как бы вы ни ссылались на него, это, вероятно, не поможет ответить на исходный вопрос, который касался перемещения файлов внутри каталога в указанное место.
Томасруттер
0

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

FILE=.myHiddenFile
mv "$FILE" dest/

объяснение

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

mv .myHiddenFile dest/

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

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

Хотя и ls -alпоказал, что файл и dest/существует.

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

Исайя
источник
-1

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

cp -Rp source-directory/. .
стог
источник
1
Это очень похоже на ответ Дрейка Кларриса от 2013 года. Вам есть что добавить?
Рэндалл Кук