Як я можу заставити mv (або * wildcard) переміщувати приховані файли?


133

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

Власне, я думаю, що проблема полягає не в телевізорі, а в бабі. Якщо я це роблю:

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

Що я роблю неправильно?


Відповіді:


146

Ви можете зробити це:

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), також використовуйте шаблон ..?*.


Будь ласка, ознайомтесь із доповненнями, які я виклав у нижній частині запитання. Дякую.
Кухар Randall

1
Нічого невірно, .і ..це спеціальні dir : відповідно поточний dir & батьків dir . Це просто попередження. Краще використовувати shopt -s dotglobрішення
Жиль Кінот

Я закінчила лише два кроки: mv home/rcook/* /home/rcook/слідом за ними mv home/rcook/.* /home/rcook/. Це зробило трюк, хоча я б хотів, щоб я перейшов за посиланням і прочитав спочатку про режим dotglob. Це врятувало б мені крок. +1
Кухар Randall

Тож другий підхід вимагає використання абсолютних шляхів?
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файл, який я мав явно вирішити свою проблему.
HeyWatchЦе

Якщо ненульовий код виходу є проблемою, ви можете придушити його, наприклад, додавши || :( ||означає виконати наступне для false / error, :це команда noop). Але це також пригнічує легітимні помилки, наприклад, папка призначення не існує. Я не можу знайти більш елегантний спосіб за допомогою mvвиключення .та ..записів. Мені великий плюс для CP не є написання нових файлів на диск.
Ендрю Шварц

10

Якщо ви ls -lзнаходитесь в каталозі, ви побачите .і ..серед перелічених файлів. Отже, я думаю, mv .* /destвраховує ці покажчики. Спробуйте:

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

це ігнорує ці поточні та батьківські режими покажчиків.

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


Приємно. Аналогічна відповідь на цей стиль глобінгу є тут: superuser.com/a/784046/144977 . Дякуємо, що опублікували це.
фіат

7

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

cp -Rp . /desired/directory

тоді ви можете видалити вихідні файли з поточного каталогу

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

mv $(ls -A) /desired/directory

4
Копіювати-потім-видаляти дуже відрізняється від переміщення, якщо джерело та ціль знаходяться в одній файловій системі. Принаймні включіть можливість -pзбереження метаданих. Використання lsмає бути в крайньому випадку, і тут є кращі, простіші способи.
Жиль

2

Насправді не існує такого поняття, як "приховані" файли в Linux. Файли, які починаються з крапки, за замовчуванням просто приховані від списків файлів.

Щоб скопіювати файли навіть з глобусом, вам потрібно встановити префікс файлу з .таким, як, mv -u .* fooа потім .fooз'явиться, як foo/.fooпри переміщенні.

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


Будь ласка, ознайомтесь із доповненнями, які я виклав у нижній частині запитання. Дякую.
Кухар Randall

0

Отже, ми маємо:

a
|-- .foo
`-- bar

і:

b

Я зайняв величезний час, знайшовши краще рішення, ніж усі відповіді тут.

Потім мені знадобилося 30 секунд для цієї команди:

$ mv --help

Тоді я знайшов своє кохання:

$ mv a/ b/ -T

Примітка: я навіть аргументу не розумію -T. Він просто робив те, що мені потрібно. Тут написано:

-T, --no-target-каталог трактує DEST як звичайний файл


1
Якщо пропустіть косу рису, вам це не потрібно -T. Так чи інакше, це по суті означає, що mv рухає сам каталог, а не переміщує всі файли всередині нього.
thomasrutter

@thomasrutter, чи не переміщення самого каталогу те саме, що перейменування?
Кухар Рендалл

3
Так, якщо батьківське призначення залишається таким же, по суті це просто перейменувати його. Однак ви посилаєтесь на нього, це, ймовірно, не допомагає відповісти на початкове запитання, яке стосувалося переміщення файлів всередині каталогу в задане місце.
thomasrutter

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 року. Чи є ще щось додати?
Randall Cook
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.