Как переместить все файлы из текущего каталога в верхний каталог?


133

Как переместить все файлы из текущего каталога в верхний каталог в Linux?

Я пробовал что-то вроде mv *.*, но это не работает.


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

Я пометил этот вопрос по запросу Stephan202.
одиннадцать81

Ответы:


202

Команда, которую вы ищете

mv * .[^.]* ..

или (см. ниже для получения дополнительной информации):

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

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

Смотрите man-страницу, на которую я ссылаюсь, для получения дополнительной информации mv.


Почему .[^.]*вместо .*?

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

Как указывает Паггас , нам также нужно добавить шаблон , чтобы сопоставить файлы, начинающиеся с двух точек. Смотрите его ответ для альтернативного решения, используя ..??*find

В ответеshopt Арджана упоминается , чтобы избежать всех этих проблем с точечными файлами. Но тогда проблема с файлами начинается с тире. И это требует трех команд. Тем не менее, мне нравится идея. Я предлагаю использовать это так:

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

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


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

1
@alain: пожалуйста, и добро пожаловать на сайт! (Если (и только если) одно из сообщений здесь достаточно ответило на ваш вопрос, то вы можете пометить его как таковое. Это принесет постеру 15 дополнительных очков репутации, а также даст вам 2 дополнительных репутации.)
Stephan202

Мне очень нравится, что шоппинг-решение работает в
недрах

2
В синтаксисе *. * Нет никакого вреда - в том числе .. опасен только при использовании с chmod и chown и флагом "recurse", т.е. chmod -R или chown -R. И в этих случаях никогда не набирайте chown. * Или chmod. * - выбирайте верхний каталог в пути, который вы ищете, и используйте -h (не переходите по символическим ссылкам). Но, г-н .. просто ничего не делает, так что не беспокойтесь об этом.
Крис

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
Кроме того, я забыл отметить важность - чтобы команда корректно работала с именами файлов, начинающимися с тире. Я включил - в моем ответе найти все же. Более полный ответ с использованием globs: "mv - *. [^.]. ?? * ..".
Paggas

+1: я вернулся, чтобы добавить ..?*свой комментарий, и вы уже позаботились об этом.
Крис Джонсен

1
Что может быть не так при попытке mv ..? Он просто ничего не делает и ничего не может сделать. Есть другие команды, где он может что-то делать (chmod и chown), но mv и rm просто ничего не делают. или ..
Крис

1
Это дает mv: нелегальный вариант - t
pal4life

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

14

Ради полноты можно также указать оболочке Bash включить скрытые файлы, используя shopt:

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

+1. Гораздо чище. Я думаю, что небольшое улучшение в порядке, хотя. Смотрите обновление к моему ответу.
Stephan202

8

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

cp -rf . ..

rm -rf *

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


Предупреждение Если вы перемещаетесь в одной и той же файловой системе , в большинстве случаев вы на самом деле не копировали файлы, а только обновляли записи каталога без перемещения inode или файловых компонентов. Смотрите даже [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. ничего не делает
Крис

2

Эта свернутая команда работает на большинстве современных оболочек:

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

В противном случае упоминается портативное решение:

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

Функции:

  1. \ предотвращает нежелательное изменение псевдонимов.

  2. - предотвращает интерпретацию имен файлов, содержащих начальные дефисы (-xyz), в качестве аргументов командной строки.

  3. . [^.] соответствует всем именам файлов из двух символов, начинающимся с. Кроме ..

  4. . ?? * соответствует всем другим именам файлов не более трех символов.

Наивные реализации:

  1. Следующее пропускает скрытые имена файлов UNIX, начинающиеся с. (.Bashrc).

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

    mv .* ..
    

2

Это более правильно использовать шаблон , * .[!.] .??*чем , * .[^.] .??*так как первый будет также работать со старыми оболочками , такими как ksh88:

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

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


0

Найти и grep работы тоже. Такая структура может быть полезна, если вы хотите выбрать файлы по более сложным критериям, изменив find и egrep.

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

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

0

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

mv "`ls`" ../

или, если есть скрытые файлы / каталоги

использовать:

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

Также, допустим, вы хотите переместить содержимое какой-либо папки в одну из ее внутренних папок tony (скажем)

использовать:

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 ../он также работал бы по необходимости. Да, он покажет те ошибки, как я упоминал выше, но кроме этого он переместит необходимые папки / файлы в родительский каталог.
Прабхат Кумар Сингх

Это не будет работать для файлов с пробелами.
Кенорб

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