Как переместить все файлы из текущего каталога в верхний каталог?
Как переместить все файлы из текущего каталога в верхний каталог в Linux?
Я пробовал что-то вроде mv *.*
, но это не работает.
11 ответов
Команда, которую вы ищете
mv * .[^.]* ..
или (см. ниже для получения дополнительной информации):
(shopt -s dotglob; mv -- * ..)
Пояснение: mv
Команда перемещает файлы и каталоги. Последний аргумент mv
является целью (в этом случае каталог на один шаг вверх по дереву, ..
). Аргументами до этого являются исходные файлы и каталоги. Звездочка (*
) является подстановочным знаком, который соответствует всем файлам, которые не начинаются с точки. Файлы, начинающиеся с точки (точечные файлы), являются "скрытыми". Они сопоставлены с использованием шаблона .[^.]*
(см. правку ниже).
Смотрите man-страницу, на которую я ссылаюсь, для получения дополнительной информации о mv
,
Зачем .[^.]*
вместо .*
?
Как правильно указывает Chris Johnsen: шаблон .*
также соответствует .
а также ..
, Поскольку вы не хотите (и не можете) перемещать их, лучше использовать шаблон, который соответствует любому имени файла, начинающемуся с точки, кроме этих двух. Шаблон .[^.]*
делает только это: оно соответствует любому имени файла (1), начинающемуся с точки (2), за которой следует символ, который не является точкой (3), за которой следует ноль или более произвольных символов.
Как указывает Paggas, мы также должны добавить шаблон .??*
чтобы сопоставить файлы, начинающиеся с двух точек. Смотрите его ответ для альтернативного решения, используя find
,
В ответе Арджана упоминается shopt
чтобы избежать всех этих проблем с точечными файлами. Но тогда проблема с файлами начинается с тире. И это требует трех команд. Тем не менее, мне нравится идея. Я предлагаю использовать это так:
(shopt -s dotglob; mv -- * ..)
Это выполняет shopt
в скорлупе (таким образом, нет второго вызова shopt
требуется) и использует --
так что файлы, начинающиеся с тире, не будут интерпретироваться как аргументы mv
,
Краткий ответ: используйте
find . -mindepth 1 -maxdepth 1 -exec mv -t.. -- {} +
Длинный ответ:
Команда
mv * .* ..
не будет работать с .*
может соответствовать .
а также ..
, Но команда
mv * .[^.]* ..
тоже не сработает, т.к. .[^.]*
не будет соответствовать, например, ..filename
! Вместо этого я делаю
mv * .[^.] .??* ..
который будет соответствовать всему, кроме .
а также ..
, *
будет соответствовать всему, что не начинается с .
, .[^.]
будет соответствовать всем 2-х символьным именам файлов, начинающимся с точки, кроме ..
, а также .??*
будет соответствовать всем именам файлов, начинающимся с точки минимум с 3 символами.
А еще лучше, вы можете использовать
find . -mindepth 1 -maxdepth 1 -exec mv -t.. -- {} +
который избегает уродливых шаровых взломов в mv * .[^.] .??* ..
!
Ради полноты можно также указать оболочке Bash включить скрытые файлы, используя shopt
:
shopt -s dotglob
mv -- * ..
shopt -u dotglob
У mv отсутствует функциональность перемещения скрытых файлов при использовании *
- так почему бы не использовать копию вместо этого?
cp -rf . ..
rm -rf *
Не нужно вдаваться в сложные решения дотлогбинга и использования команд поиска.
rsync -a --remove-source-files . ..
rsync
это чрезвычайно мощный инструмент для копирования файлов, обычно используемый для выполнения эффективных инкрементных удаленных резервных копий и зеркал.
С помощью приведенной выше команды мы говорим rsync
скопировать содержимое .
в ..
Переключатель -a
позволяет рекурсию в .
подкаталоги и включает некоторые другие общие параметры.
Переключатель --remove-source-files
сообщает rsync об удалении исходных файлов после успешного копирования, т. е. заставляет rsync вести себя аналогично mv
команда.
Правильнее использовать шаблон * .[!.] .??*
чем * .[^.] .??*
поскольку первый также будет работать со старыми оболочками, такими как ksh88:
mv -- * .[!.] .??* ..
--
предотвращает проблемы, когда у вас есть имя файла, которое начинается с-
*
соответствует всем именам файлов, которые не начинаются с.
- нет имен файлов с одним символом, которые начинаются с
.
который вы можете / должны двигаться .[!.]
соответствует всем именам файлов из двух символов, которые начинаются с.
.??*
соответствует всем именам файлов (или длиннее) из трех символов, которые начинаются с.
С ksh88, шаблон имени файла .[^.]
будет фактически соответствовать именам файлов ..
(который всегда существует) и .^
(что, вероятно, не существует), оказывая влияние, противоположное желаемому.
В конечном итоге пытается mv .
потерпит неудачу, потому что mv не сможет отсоединить каталог, в котором вы сейчас находитесь. Вы можете mv * ..
переместить файлы в cwd.
Эта свернутая команда работает на большинстве современных оболочек:
\mv -- {,.{[^.],??}}* ..
В противном случае упоминается портативное решение:
\mv -- * .[^.] .??* ..
Особенности:
\ предотвращает нежелательное изменение псевдонимов.
- предотвращает интерпретацию имен файлов, содержащих начальные дефисы (-xyz), в качестве аргументов командной строки.
. [^.] соответствует всем именам файлов из двух символов, начинающимся с. Кроме..
.?? * соответствует всем другим именам файлов не более трех символов.
Наивные реализации:
Следующее пропускает скрытые имена файлов UNIX, начинающиеся с. (.Bashrc).
mv * ..
Следующее совпадение.. которое рекурсивно пытается переместить каждый каталог в конце концов обратно в / в.. текущего рабочего каталога ($PWD или pwd). Никогда не используйте.
mv .* ..
mv * .??* ../.
*
получает все не точечные файлы. .??*
получает все. файлы длиной не менее трех байтов, что работает для всех допустимых. Что-нибудь осталось, что вы, вероятно, хотите rm
скорее, чем mv
тем не мение.
../.
не предлагает никаких прямых преимуществ перед ..
но когда вы перемещаетесь в каталог, это очень хорошая привычка, потому что он потерпит неудачу, если вы захотите, если что-то не так с путем. Например, mv xyz bletch
где вы думаете bletch
каталог, можно сделать более точным с mv xyz bletch/.
,
Найти и grep работы тоже. Такая структура может быть полезна, если вы хотите выбрать файлы по более сложным критериям, изменив find и egrep.
find -maxdepth 1 | egrep '^./.' # Returns all files
mv `find -maxdepth 1 | egrep '^./.'` .. # mv <all files> ..
Я думаю, что самое простое решение для перемещения всех файлов в родительский каталог. было бы
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
,