it-swarm-ru.tech

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

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

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

131
asksuperuser

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

mv * .[^.]* ..

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

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

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

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


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

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

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

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

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

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

199
Stephan202

Краткий ответ: используйте

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

Длинный ответ:

Команда

mv * .* ..

не будет работать, так как .* может совпадать с . и ... Но команда

mv * .[^.]* ..

также не будет работать, так как .[^.]* не будет совпадать, например, ..filename! Вместо этого я делаю

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

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

А еще лучше, вы можете использовать

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

что позволяет избежать уродливых глобальных хаков в mv * .[^.] .??* ..!

42
Paggas

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

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

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

cp -rf . ..

rm -rf *

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

8
Micky Martin
rsync -a --remove-source-files . ..

rsync - чрезвычайно мощный инструмент копирования файлов, обычно используемый для выполнения эффективных инкрементных удаленных резервных копий и зеркал.

С помощью приведенной выше команды мы сообщаем rsync скопировать содержимое . в ..

Переключатель -a включает рекурсию в подкаталоги . и включает некоторые другие общие параметры.

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

6
mrucci

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

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

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

2
jrw32982

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

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

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

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

Характеристики:

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

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

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

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

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

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

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

    mv .* ..
    
2
dhchdhd

В конечном итоге попытка mv . не удастся, потому что mv не сможет отсоединить каталог, в котором вы сейчас находитесь. Вы можете mv * .. переместить файлы в cwd.

2
DaveParillo
mv * .??* ../.

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

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

2
DigitalRoss

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

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

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

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

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.

0
Prabhat Kumar Singh