Як перемістити всі файли, включаючи приховані файли, у батьківський каталог через *


113

Це повинно бути популярним питанням, але я не зміг знайти відповіді.

Як перемістити всі файли через *, включаючи приховані файли, а також до батьківського каталогу, як це:

mv /path/subfolder/* /path/

Це перемістить усі файли до батьківського каталогу, як очікувалося, але не перемістить приховані файли. Як це зробити?


1
на це питання є дублікат у SU , з ще правильнішою відповіддю (не прийнята, хоча): cp -r /path/to/source/. /destination
Флоріан

Відповіді:


202

Ви можете знайти повний набір рішень щодо цього у відповіді UNIX та Linux на тему: Як переміщувати всі файли (включаючи приховані) з одного каталогу в інший? . Він показує рішення в Bash, zsh, ksh93, standard (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, щоб включити приховані файли та приховані каталоги та їх вміст? )


2
Дужки - це лише короткий відрізок mv /path/subfolder/* /path/subfolder/.* /path/, не суворо необхідний для об'єднання двох команд в одну.
чепнер

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 я думаю, що це буде
Jesús Carrera

7
"Просто ігноруйте попередження" не завжди може бути хорошою ідеєю. Зараз у мене виникають проблеми зі сценарієм, у якому мені потрібно зупинити виконання, якщо якийсь крок не вдався - оскільки це рішення завжди викликає помилку, воно вбиває мій сценарій. Мені потрібен спосіб визначити, не вдалося чи ні команда mv ...
MarioVilas

29

Я думаю, що це найелегантніше, оскільки воно також не намагається рухатись ..:

mv /source/path/{.[!.],}* /destination/path

1
так, я помітив, що це повідомлення про помилки також приємне.
Йосип Астрахан

Я думаю, що це дуже вдале рішення, але важко запам'ятати цю схему
Ділан Б

це буде НЕ вистачати файли , як ..anythingі ...anythingт.д. - stackoverflow.com/a/31438355/2351568 містить правильне регулярний вираз для цієї проблеми. || але все shopt -s dotglobодно краще рішення!
DJCrashdummy

@DylanB не запам'ятовує це. пам'ятайте, що він відповідає тому, що знаходиться у фігурних дужках, розділених комами. {a,b}*знайде всі файли, що починаються з a або b, такі як "анатомія" та "бульдозер". Другий збіг - це лише порожня відповідність, рівнозначна *, а перша відповідність є рівнозначною .[!.], де група [!.]означає групу, яка НЕ ​​починається з а .. Це означає, .*але ні ..*.
мазунки

28

Це перемістить усі файли до батьківського каталогу, як очікувалося, але не перемістить приховані файли. Як це зробити?

Ви можете ввімкнути dotglob:

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

Щоб вимкнути dotglob, вам потрібно буде сказати:

shopt -u dotglob

Дуже корисний. Хотів дізнатися більше, але знятий є вбудованим, тому man shoptне працює і help shoptдуже короткий. Але ви можете зробити bashman () { man bash | less -p "^ $1 "; }і потім bashman shoptпрочитати все про це прямо. (Можливо, вам доведеться натиснути n, щоб перейти до команди, якщо є рядки, що починаються з пострілу, як я знайшов.)
Нік Райс

2
це вплине і на всі інші команди на кшталт ls.. таким чином, не дуже того, що ви хотіли б, мабуть
phil294

5

Альтернативним простішим рішенням є використання rsyncутиліти:

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

Примітка. Команда вгорі покаже, що буде змінено. Щоб виконати фактичні зміни, видаліть--dry-run .

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

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

Використовуваний -uпараметр буде пропускати існуючі новіші файли, -rповторюватись в каталогах і -vзбільшить багатослівність.


Найкраще рішення будь-коли! У моєму випадку я просто видалив параметр -u, тому що я не хотів би оновлювати кореневу папку. Спасибі
Thales Ceolin

Це одна з тих команд, де, якщо ви не будете обережні, ви дійсно можете зіпсувати речі для себе в Linux, назавжди. Будь ласка, оновіть свою відповідь, щоб включити sudo перед командою rsync, інакше користувачі можуть легко отримати дозвіл відхилено для mkdir, але видалення файлів все-таки рухатимуться вперед, таким чином, команда rsync видалить увесь каталог, який ви хочете перемістити, і більше нічого не робити . Ви втратите весь свій каталог. Як тільки ви додасте судо до своєї відповіді, це, мабуть, має бути прийнятою відповіддю. Отже, команда повинна бути: sudo rsync -vuar --delete-after path / підпапка / шлях /
Blue Water

@JohnnyB Вибачте за незручності. Я додав sudoі --dry-run, тому люди можуть перевірити зміни перед запуском фактичної команди, щоб уникнути будь-якого потенційного безладу.
kenorb

О, я не розумів, що існує варіант - пробігати. Гарне доповнення. Не потрібно вибачення. Це чудово.
Блакитна вода

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

Найкраще ввімкнути його, коли закінчите, інакше ви будете плутати речі, які припускають, що це буде вимкнено.


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командою, як я описав вище, усуває всі ці проблеми.


2

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

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

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

Зауважте, що вихідний шлях не закінчується символом/ (тому всі файли / каталоги та файли файлів копіюються)

Каталог призначення закінчується тим/ , що ми розміщуємо вміст вихідної папки до цільового пункту в цілому.


Хоча yesце дивовижна команда, яка використовується, якщо ви хочете переотримати цільові файли, що не завжди бажано. Використовуйте його лише в тому випадку, якщо ви впевнені, що хочете це зробити. Також, чи є різниця між yes | cp ...і cp -f ...?
мазунки
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.