Як перемістити всі файли з поточного каталогу у верхній каталог?


133

Як перемістити всі файли з поточного каталогу до верхнього каталогу в Linux?

Я спробував щось подібне mv *.*, але це не виходить.


У мене не вистачає представника для повторного позначення питань, але чи можу я запропонувати [linux] [mv] [cwd] [files], чи щось подібне?
Stephan202

Я змінив це питання на запит Stephan202.
одинадцять81

Відповіді:


202

Команда, яку ви шукаєте, така

mv * .[^.]* ..

або (див. нижче для отримання додаткової інформації):

(shopt -s dotglob; mv -- * ..)

Пояснення: mvкоманда переміщує файли та каталоги. Останній аргумент mv- це ціль (у цьому випадку каталог один крок "вгору" в дереві, ..). Аргументи до цього - це вихідні файли та каталоги. Зірочка ( *) - це майна, яка відповідає всім файлам, які не починаються з крапки. Файли, які починаються з крапки (dotfiles), "приховані". Вони узгоджуються за допомогою шаблону .[^.]*(див. Редагування нижче).

Для отримання додаткової інформації дивіться сторінку, яку я пов’язав mv.


Чому .[^.]*замість .*?

Як правильно зазначає Кріс Джонсен : модель .*також відповідає .і ... Оскільки ви не хочете (і не можете) їх переміщувати, краще використовувати шаблон, який відповідає будь-якому імені файлу, починаючи з крапки, крім цих двох . Шаблон .[^.]*робиться саме так: він відповідає будь-якому імені файлу (1), починаючи з крапки (2), а потім символу, який не є крапкою (3), а за нулем або більше довільних символів.

Як Paggas вказує , ми також повинні додати шаблон .??*, щоб відповідати файли , що починаються з двох точок. Дивіться його відповідь щодо використання альтернативного рішення find.

У відповіді Ар'яна згадується shopt, щоб уникнути всіх цих питань з точковими файлами. Але тоді проблема з файлами починається з тире. А для цього потрібні три команди. Все-таки ідея мені подобається. Я пропоную використовувати його так:

(shopt -s dotglob; mv -- * ..)

Це виконується shoptв підрозділі (таким чином, не shoptвимагається другий виклик ) і використовує --так, що файли, що починаються з тире, не трактуватимуться як аргументи mv.


7
Використання .*може викликати mv для створення попереджень / помилок про неможливість переміщення .та ... Ви можете спробувати mv * .[^.]* ...
Кріс Джонсен

1
@alain: ласкаво просимо на сайт! (Якщо (і лише якщо) один із постів тут достатньо відповів на ваше запитання, ви можете позначити його як таке. Це отримає плакату 15 додаткових балів репутації, а також дасть вам ще 2
повтори

Мені дуже подобається зняте рішення, яке працює в
нижній частині

2
У синтаксисі *. * Немає шкоди - включаючи .., це небезпечно лише при використанні з chmod та chown та прапором "повторюваність", тобто chmod -R або chown -R. І в цих випадках ніколи не вводьте chown. * Або chmod. * - порушуйте верхній каталог у шляху, який ви шукаєте та використовуєте -h (не слідкуйте за символічними посиланнями). Але, Mv .. просто нічого не робить, тому не турбуйтеся про це.
chris

1
Правильні три закономірності є *, .[^.]*і ..?*. Другий, можливо, .[!.]*для старих (POSIX) снарядів. Читайте також

42

Коротка відповідь: використання

find . -mindepth 1 -maxdepth 1 -exec mv -t.. -- {} +

Довга відповідь:

Команда

mv * .* ..

не працюватиме, оскільки .*може відповідати .і ... Але команда

mv * .[^.]* ..

також не працюватиме, оскільки .[^.]*не збігається, наприклад ..filename,! Натомість те, що я роблю, - це

mv * .[^.] .??* ..

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

А ще краще, ви можете використовувати

find . -mindepth 1 -maxdepth 1 -exec mv -t.. -- {} +

що дозволяє уникнути некрасивих глобальних хакерів mv * .[^.] .??* ..!


1
Також я забув відзначити важливість - щоб команда працювала правильно з іменами файлів, починаючи з тире. Я включив - хоча у своїй відповіді знайти. Більш повна відповідь за допомогою глобусів - "mv - *. [^.]. ?? * ..".
Паггас

+1: Я повернувся, щоб додати ..?*свій коментар, і ви вже подбали про це.
Кріс Джонсен

1
Що може бути не так у спробі mv ..? Він просто нічого не робить і нічого не може зробити. Є й інші команди, де він може щось робити (chmod та chown), але mv та rm просто нічого не роблять. або ..
chris

1
Це дає mv: незаконний варіант - t
pal4life

1
Боно, подвійний тире каже, mvщоб перестати шукати будь-які подальші варіанти команд. Дужки - це отримане ім'я файлу. Знак плюс говорить, що замість запуску exec за результатом (тобто за назвою файлу), покладіть якомога більше результатів в один виконавець, наскільки це можливо. Для повноти, -t..означає перемістити цільове місце призначення, щоб перемістити всі ці файли до.
Ісульдор

14

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

shopt -s dotglob
mv -- * ..
shopt -u dotglob

+1. Значно чистіше. Я думаю, що невелике поліпшення в порядку, хоча. Дивіться оновлення моєї відповіді.
Stephan202

8

У телевізора бракує функціональних можливостей переміщення прихованих файлів при використанні *- так чому б не використовувати копію замість цього?

cp -rf . ..

rm -rf *

Не потрібно вникати в складні рішення дотглобінгу та використовувати команди пошуку.


Попередження Якщо ви пересуваєтеся в одній файловій системі , то в більшості випадків ви насправді не копіювали файли, а лише оновлювали записи каталогів, не переміщуючи ідентифікаторів або файлів. Дивіться навіть [1 ]. За допомогою cpі rmзамість цього ви дійсно копіюєте все.
Гастур

6
rsync -a --remove-source-files . ..

rsync це надзвичайно потужний інструмент копіювання файлів, який зазвичай використовується для виконання ефективних віддалених резервних копій та дзеркал.

За допомогою наведеної вище команди ми rsyncхочемо скопіювати вміст .у..

Перемикач -aдає можливість рекурсії в .підкаталоги та дає змогу використовувати деякі інші загальні параметри.

Перемикач --remove-source-filesповідомляє rsync видалити вихідні файли після успішної копії, тобто змушує rsync вести себе аналогічно mvкоманді.


1
Трохи більше пояснень було б непогано.
ChrisF

Звичайно, сподіваюсь, це зараз зрозуміліше.
mrucci

Зауважте, що --remove-source-filesне буде видалено (синхронізовано) каталоги.
Денніс

Приємне, прийняте рішення дає мені -bash: /bin/mv: Argument list too longпомилку. Цей працює як принадність.
userlond

2

Зрештою, спроба mv .не вдасться, тому що mv не зможе від’єднати каталог, у якому ви зараз перебуваєте. Ви можете mv * ..перемістити файли в cwd.


2
mv * .??* ../.

*отримує всі неточні файли. .??*отримує все. файли принаймні три байти, що працює для всіх законних. Все, що ви залишили, напевно, хочете, rmа не mvвсе одно.

../.Не дає ніяких прямих переваг по порівнянні , ..але при виконанні крок-в-каталог це дуже хороша звичка, тому що вона НЕ буде виконана, як ви хочете, якщо є що - то не так зі шляху. Наприклад, mv xyz bletchтам, де ви думаєте bletch , що це каталог, можна зробити більш впевненим mv xyz bletch/..


2
Ви можете додати, .[^.]щоб отримати схожі файли .a.
Кріс Джонсен

Різниці між ../ та ../ немає. тож я б не переймався набирати. після нахилу. Також у випадку з mv та rm не шкода включати. і .. у списку, тобто немає нічого страшного чи неправильного з mv *. * / path / to / file /, як rm. або навіть -rf. нічого не робить.
chris

2

Ця мінімізована команда працює на більшості сучасних оболонок:

\mv -- {,.{[^.],??}}* ..

В іншому випадку є портативне рішення:

\mv -- * .[^.] .??* ..

Особливості:

  1. \ заважає псевдонімам не бажано змінювати mv.

  2. - запобігає інтерпретації назви файлів, що містять провідні дефіси (-xyz), як аргументи командного рядка.

  3. . [^.] відповідає всім двом іменам символів, починаючи з. крім ..

  4. . ?? * відповідає всім іншим іменам три символи або довше.

Наївні втілення:

  1. Наступні пропускає приховані імена файлів UNIX, ті, що починаються з. (.bashrc).

    mv * ..
    
  2. Наступні збіги .., які рекурсивно намагаються перемістити кожен каталог, врешті-решт, назад до / в .. поточного робочого каталогу ($ PWD або pwd). Ніколи не використовуйте.

    mv .* ..
    

2

Правильніше використовувати шаблон, * .[!.] .??*ніж * .[^.] .??*коли перша також буде працювати зі старими оболонками, такими як ksh88:

mv -- * .[!.] .??* ..
  • -- запобігає проблемам, коли у вас є ім'я файлу, з якого починається -
  • * відповідає всім іменам файлів, які не починаються з .
  • не існує жодного імені файлів символів, які починаються з того, .який ви можете / повинні перемістити
  • .[!.] відповідає всім двом іменам файлів символів, які починаються з .
  • .??* відповідає усім трьом іменам файлів символів (або довше), які починаються з a .

Що стосується ksh88, шаблон імені файлів .[^.]насправді буде відповідати назвам файлів ..(які завжди існують) та .^(які, ймовірно, не існують), матиме ефект, протилежний бажаному.


0

Знайдіть і виконайте роботу теж. Така структура може бути корисною, якщо ви хочете вибрати файли за складнішими критеріями, змінивши find і egrep.

find -maxdepth 1 | egrep '^./.'         # Returns all files

mv `find -maxdepth 1 | egrep '^./.'` .. # mv <all files> ..

0

Я думаю, що найпростіше рішення для переміщення всіх файлів у його батьківський dir. був би

mv "`ls`" ../

або, якщо є приховані файли / каталоги

використання:

mv "`ls -a`" ../ 2>/dev/null

Крім того, скажемо, що ви хочете перемістити вміст якоїсь папки в одну з її внутрішньої папки (скажіть)

використання:

mv "`ls -a`" /tony 2>/dev/null

Примітка:

"`ls -a`" 

Переміщення файлів із пробілами.

2>/dev/null

Є чи для придушення попередження / помилки , тому що ls -aбуде друкувати .і ..папки , а також і ви не можете переміщати або копіювати їх. Так що для цих папок буде показано помилку (якщо ми не використовуємо 2> / dev / null), що вона не може їх перемістити, а решта буде зручно переміщуватись.

Краще уникати, ls -aякщо немає прихованих файлів, а просто використовувати ls.


Ви спробували, що станеться, коли біжите mv $(ls -a)? Це торкнеться поточного каталогу та каталогу під ним, тому що також ls -aбуде видаватися ...
Самі Лайн

Дякую, @SamiLaine за пропозицію я вніс виправлення. Але mv ls -a ../він також працював би за потребою. Так, він покаже ті помилки, як я згадував вище, але крім того, що він перемістить необхідні папки / файли до батьківського dir.
Прабхат Кумар Сінгх

Це не працюватиме для файлів з пробілами.
kenorb

@kenorb Вам потрібно подвійно процитувати lsкоманду для переміщення файлів з пробілами. Я вніс необхідні зміни. Дякуємо, що вказали.
Прабхат Кумар Сінгх
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.