Как переместить все файлы, включая скрытые, в родительский каталог через *

113

Наверное, это популярный вопрос, но я не мог найти ответа.

Как переместить все файлы через *, включая скрытые файлы, в родительский каталог, например:

mv /path/subfolder/* /path/

Это переместит все файлы в родительский каталог, как и ожидалось, но не переместит скрытые файлы. Как это сделать?

TroodoN-Майк
источник
1
у этого вопроса есть дубликат в SU , с еще более правильным ответом (хотя и не принятым): cp -r /path/to/source/. /destination
Флориан

Ответы:

202

Вы можете найти исчерпывающий набор решений по этому поводу в ответе UNIX и Linux на вопрос Как переместить все файлы (включая скрытые) из одного каталога в другой? . Он показывает решения на Bash, zsh, ksh93, стандартном (POSIX) sh и т. Д.


Вы можете использовать эти две команды вместе:

mv /path/subfolder/* /path/   # your current approach
mv /path/subfolder/.* /path/  # this one for hidden files

Или все вместе ( спасибо pfnuesel ):

mv /path/subfolder/{.,}* /path/

Что расширяется до:

mv /path/subfolder/* /path/subfolder/.* /path/

(пример: echo a{.,}bрасширяется до a.b ab)

Обратите внимание, что это покажет пару предупреждений:

mv: cannot move ‘/path/subfolder/.’ to /path/.’: Device or resource busy
mv: cannot remove /path/subfolder/..’: Is a directory

Просто игнорируйте их: это происходит потому, что /path/subfolder/{.,}*также расширяется до /path/subfolder/.и /path/subfolder/.., которые являются каталогом и родительским каталогом (см. Что означают «.» И «..» в папке? ).


Если вы хотите просто скопировать, вы можете использовать просто:

cp -r /path/subfolder/. /path/
#                     ^
#                     note the dot!

Это скопирует все файлы, как обычные, так и скрытые, поскольку /path/subfolder/.расширяется до «всего из этого каталога» (Источник: Как скопировать с помощью cp, чтобы включить скрытые файлы и скрытые каталоги и их содержимое? )

fedorqui 'ТАК, хватит вредить'
источник
2
Фигурные скобки - это всего лишь сокращение mv /path/subfolder/* /path/subfolder/.* /path/, не обязательно для объединения двух команд в одну.
chepner
7
Я получаю следующую ошибку:mv: overwrite `/path/.'? y mv: cannot move `/path/subfolder/.' to `/path/.': Device or resource busy mv: overwrite `/path/..'? y mv: cannot move `/path/subfolder/..' to `/path/..': Device or resource busy
Dejan
@Dejan Просто не обращай на это внимания. .обозначает текущий каталог и ..обозначает upкаталог. Вы, наверное, заметили, что все остальные файлы перемещены.
Дебипрасад
Стоит упомянуть, что сочетание фигурных скобок работает не для всех оболочек, но команда @chepner, я думаю, будет
Хесус Каррера
7
«Просто игнорируйте предупреждение» не всегда может быть хорошей идеей. Прямо сейчас у меня проблема со сценарием, в котором мне нужно остановить выполнение, если какой-либо шаг завершится неудачей - поскольку это решение всегда вызывает ошибку, оно убивает мой сценарий. Мне нужен способ определить, не удалось ли выполнить команду mv ...
MarioVilas
29

Я считаю, что это самый элегантный вариант, так как он также не пытается двигаться ..:

mv /source/path/{.[!.],}* /destination/path
Vanderstaaij
источник
1
да, я заметил, что он также выдает эти сообщения об ошибках, хорошая находка.
Джозеф Астрахан
Я думаю, что это очень хорошее решение, но этот шаблон сложно запомнить
Дилан Би
это приведет к пропуску таких файлов, как ..anythingили ...anythingт.д. - stackoverflow.com/a/31438355/2351568 содержит правильное регулярное выражение для этой проблемы. || но в любом случае использование shopt -s dotglob- лучшее решение!
DJCrashdummy
@DylanB, не запоминай. помните, что он соответствует тому, что указано в фигурных скобках, разделенных запятыми. {a,b}*найдет все файлы, начинающиеся с a или b, такие как "анатомия" и "бульдозер". Второе совпадение - это просто пустое совпадение, эквивалентное *, а первое совпадение эквивалентно .[!.], где группа [!.]означает группу, НЕ начинающуюся с .. Это значит, .*но нет ..*.
mazunki
28

Это переместит все файлы в родительский каталог, как и ожидалось, но не переместит скрытые файлы. Как это сделать?

Вы могли включить dotglob:

shopt -s dotglob               # This would cause mv below to match hidden files
mv /path/subfolder/* /path/

Чтобы выключить dotglob, вам нужно будет сказать:

shopt -u dotglob
Devnull
источник
Очень полезно. Хотел узнать больше, но магазин является встроенным, поэтому man shoptон не работает и help shoptочень краток. Но вы можете сделать bashman () { man bash | less -p "^ $1 "; }и потом bashman shoptпрочитать все об этом прямо. (Возможно, придется нажать n, чтобы перейти к команде, если есть строки, начинающиеся с shopt, как я обнаружил.)
Ник Райс,
2
это также повлияет на все другие команды, такие как ls... таким образом, это не совсем то, что вам нужно, вероятно
phil294
5

Альтернативное более простое решение - использовать rsyncутилиту:

sudo rsync -vuar --delete-after --dry-run path/subfolder/ path/

Примечание. Вышеупомянутая команда покажет, что будет изменено. Чтобы выполнить фактические изменения, удалите--dry-run .

Преимущество заключается в том, что исходная папка ( subfolder) будет удалена вместе с частью команды, и при использовании mvздесь примеров вам все равно нужно очистить свои папки, не говоря уже о дополнительной головной боли, чтобы скрыть скрытые и не скрытые файлы в одном единственном шаблон.

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

Параметр used -uбудет пропускать существующие более новые файлы, -rрекурсивно перемещаться по каталогам и -vповышать уровень детализации.

Kenorb
источник
Лучшее решение! В моем случае я просто удалил параметр -u, потому что мне не хотелось бы обновлять корневую папку. Спасибо
Thales Ceolin
Это одна из тех команд, где, если вы не будете осторожны, вы можете навсегда испортить себе жизнь в Linux. Пожалуйста, обновите свой ответ, включив sudo перед командой rsync, иначе пользователи могут легко получить Permission Denied для mkdir, но удаление файлов, тем не менее, будет продолжаться, поэтому команда rsync удалит весь ваш каталог, который вы хотите переместить, и больше ничего не сделает . Вы потеряете весь свой каталог. После того, как вы добавите sudo к своему ответу, это, вероятно, должен быть принятый ответ. Итак, команда должна быть такой: sudo rsync -vuar --delete-after path / subfolder / path /
Blue Water
@JohnnyB Приносим извинения за неудобства. Я добавил sudoи --dry-run, чтобы люди могли протестировать изменения перед запуском фактической команды, чтобы избежать возможного беспорядка.
kenorb
О, я не знал, что есть опция --dry-run. Хорошее дополнение. Не нужно извиняться. Это отлично.
Голубая вода
3

Разрешите представить вам моего друга «дотглоб». Он включается и выключается вне зависимости от того, есть ли в "*" скрытые файлы.

$ mkdir test
$ cd test
$ touch a b c .hidden .hi .den
$ ls -a
. ..  .den  .hi .hidden a b c

$ shopt -u dotglob
$ ls *
a b c
$ for i in * ; do echo I found: $i ; done
I found: a
I found: b
I found: c

$ shopt -s dotglob
$ ls *
.den  .hi .hidden a b c
$ for i in * ; do echo I found: $i ; done
I found: .den
I found: .hi
I found: .hidden
I found: a
I found: b
I found: c

По умолчанию он выключен.

$ shopt dotglob
dotglob         off

Лучше всего снова включить его, когда вы закончите, иначе вы запутаете вещи, которые предполагают, что он будет выключен.

TomOnTime
источник
3

Используя findкоманду вместе с mvкомандой, вы можете предотвратить mvпопытку команды переместить каталоги (например, ..и .) и подкаталоги. Вот один вариант:

find /path/subfolder -maxdepth 1 -type f -name '*' -exec mv -n {} /path \;

Есть проблемы с некоторыми другими предоставленными ответами. Например, каждый из следующих будет пытаться переместить подкаталоги из исходного пути:

1) mv /path/subfolder/* /path/ ; mv /path/subfolder/.* /path/
2) mv /path/subfolder/{.,}* /path/ 
3) mv /source/path/{.[!.],}* /destination/path

Кроме того, 2) включает расширение. и .. файлы и 3) пропускает такие файлы, как ..foobar, ... barfoo и т. д.

Вы можете использовать,, mv /source/path/{.[!.],..?,}* /destination/pathкоторый будет включать файлы, пропущенные в пункте 3), но он все равно будет пытаться переместить подкаталоги. Использование findкоманды с mvкомандой, описанной выше, устраняет все эти проблемы.

teancum144
источник
2

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

yes | cp -rvp /source/directory /destination/directory/

yesпредназначен для автоматической перезаписи файлов назначения, rрекурсивного, vподробного, pсохранения разрешений.

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

Целевой каталог заканчивается тем,/ что мы помещаем содержимое исходной папки в место назначения в целом.

Раджниш Гадж
источник
Хотя yesэто отличная команда, которую можно использовать, если вы хотите переопределить файлы назначения, это не всегда желательно. Используйте его только в том случае, если вы уверены, что хотите это сделать. Кроме того, есть ли разница между yes | cp ...и cp -f ...?
mazunki