Переместить все файлы, кроме одного

155

Как я могу переместить все файлы, кроме одного? Я ищу что-то вроде:

'mv ~/Linux/Old/!Tux.png ~/Linux/New/'

где я перемещаю старые вещи в новые вещи - папки, кроме Tux.png. ! -знак представляет собой отрицание. Есть ли какой-нибудь инструмент для работы?

Лео Леопольд Герц 준영
источник

Ответы:

142

Если вы используете bash и у вас установлена extglobопция оболочки (как обычно):

mv ~/Linux/Old/!(Tux.png) ~/Linux/New/
STH
источник
1
Я понял что-то не так, когда протестировал команду для многих элементов: mv ~ / Linux / Old /! (Tux.png Tux1.png Tux2.png) ~ / Linux / New / Она опустошает весь старый -каталог. Что случилось?
Лео Леопольд Герц
5
@UnixBasics, попробуйте: ~ / Linux / Old /! (Tux.png | Tux1.png | Tux2.png)
Джулиано,
@Juliano Очень классная команда! Есть ли еще математические операции, такие как OR или XOR? Я предполагаю, что труба для AND.
Лео Леопольд Герц
@ UnixBasis, да. Взгляните на gnu.org/software/bash/manual/html_node/Pattern-Matching.html
Джулиано,
@Juliano Я довольно запутался в таких шаблонах, как: mv ~ / Linux /? (Tux * .png) ~ / Linux / New / mv ~ / Linux / + (Tux * .png) ~ / Linux / New / В первом Я хотел переместить 0-1 Tux -photo. В последнем я хотел переместить 1-н фотографии Tux. Они двигались все. Зачем? Можно ли переместить определенное количество фотографий?
Лео Леопольд Герц 준영
97

Поместите следующее в ваш .bashrc

shopt -s extglob

Это расширяет регулярные выражения. Затем вы можете переместить все файлы, кроме одного,

mv !(fileOne) ~/path/newFolder

Исключения по отношению к другим командам

Обратите внимание, что при копировании каталогов прямая вспышка не может использоваться в имени, как отмечено в потоке. Почему extglob, кроме разрыва, кроме условия? :

cp -r !(Backups.backupdb) /home/masi/Documents/

так Backups.backupdb/что здесь не так до отрицания, и я бы не стал использовать его ни в перемещении каталогов из-за риска неправильного использования, а затем с другими командами и возможными другими исключениями.

Лео Леопольд Герц 준영
источник
3
Это на самом деле правильный ответ. Мой был совершенно неправ; К счастью, я использовал его в папке с несколькими файлами. Вот больше информации о методе, который показывает Маси: wiki.bash-hackers.org/syntax/pattern Перейдите на «Расширенный язык шаблонов», и вы найдете больше информации об этом. Спасибо @ paul-whittaker за указание на проблему.
Mimoralea
Это старый ответ, но он все еще действителен. Я использую Ubuntu 18 и extglob, кажется, включен по умолчанию (я не покупал его). Я использовал следующую команду, чтобы переместить все файлы в текущем каталоге в архив, который также находится в этом каталоге, НЕ включая любые другие архивные папки: mv !(arc*) archive_190629b
TonyG
70

Я бы пошел с традиционным способом find & xargs:

find ~/Linux/Old -maxdepth 1 -mindepth 1 -not -name Tux.png -print0 | 
    xargs -0 mv -t ~/Linux/New

-maxdepth 1делает это не искать рекурсивно. Если вы заботитесь только о файлах, вы можете сказать -type f. -mindepth 1заставляет не включать сам ~/Linux/Oldпуть в результат. Работает с любыми именами файлов, в том числе с теми, которые содержат символы новой строки.

В одном комментарии отмечается, что -tопция mv является, вероятно, расширением GNU. Для систем, у которых его нет

find ~/Linux/Old -maxdepth 1 -mindepth 1 -not -name Tux.png \
    -exec mv '{}' ~/Linux/New \;
Йоханнес Шауб - Литб
источник
1
Проголосовал, так как он поощряет изучение мощного инструмента, найти. Обратите внимание, что для файлов с пробелами это не сработает. Рассмотрите "find -print0 | xargs -0" или иначе откажитесь от xargs: "find [что вы сказали] -exec mv -t {} ~ / Linux / New \;"
Джейсон Смит
Если ваша команда mv не имеет опции -t, то либо используйте «find ... -exec mv {} Linux / New \;» или "найти ... | xargs -I {} mv {} Linux / New". Опция -t, похоже, является расширением GNU, что хорошо для Linux, но, вероятно, не в других местах.
Роб Кеннеди
Jhs, о, я не могу. я почему-то думал, что XARGS разделены на новые строки, но не на пробелы. похоже, что я перепутал это с "прочитанным" :) плохо исправлю это
Йоханнес Шауб - Lit
Большое спасибо за отличный совет! Я собирался выбрать что-то, потому что это нацелено на вопрос. Однако позже я почувствую полезность ваших команд, поэтому я должен выбрать способ «найти и xargs». Это просто качается. Спасибо :)
Лео Леопольд Герц t
Способ сложный. Ответ Маси является более полным, более простым и, следовательно, более правильным
user637338
30

Быстрый способ - изменить имя файла смокинга, чтобы ваша команда перемещения не соответствовала.

Например:

mv Tux.png .Tux.png

mv * ~/somefolder

mv .Tux.png Tux.png
Джон Т
источник
не используйте " . ", так как это будет перемещать только файлы, которые имеют "." во имя. Просто "*" достаточно.
Juliano
1
Если вы измените его на *, он также удалит переименованный файл.
Джон Т
6
@ Джон Т: Нет, глобус * не соответствует файлам, которые начинаются с точки.
Билл Карвин,
Это лучший ответ на сегодняшний день. Нет необходимости изменять или комментировать этот ответ. 100 баллов. Большое спасибо. Отлично сработано!
Стив К
23

Я думаю, что самый простой способ сделать это с помощью клюшки

mv `ls -1 ~/Linux/Old/ | grep -v Tux.png` ~/Linux/New/

Редактировать:

Вместо этого используйте обратную косую черту с ls, чтобы не использовать ее с псевдонимом, т. Е. В основном ls имеет псевдоним ls --color.

mv `\ls -1 ~/Linux/Old/ | grep -v Tux.png` ~/Linux/New/

Спасибо @Арнольд Роа

Рохал Аббас
источник
1
Можете ли вы объяснить, почему вы используете grep -vтам?
Лео Леопольд Герц 준영
1
Опция -v в grep исключает результат, это все равно что взять все, кроме Tux.png
Рохайл Аббас
1
Это, конечно, интуитивно понятно, но ответы выше лучше. Например, если вы пишете сценарий, это потребует, чтобы вы были в правильном каталоге ..
nJGL
@nJGL Здесь мы также можем указать абсолютный путь, я использовал homedirectory (~), так как у него был вопрос
Рохайл Аббас
@RohailAbbas Достаточно справедливо. ✌️
nJGL
14

Для bash ответ правильный. Вот синтаксис zsh (мой выбор оболочки):

mv ~/Linux/Old/^Tux.png ~/Linux/New/

Требуется EXTENDED_GLOBопция оболочки для установки.

Жулиано
источник
3
Что если мы хотим исключить два файла?
mpen
13

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

ls -1 | grep -v ^$EXCLUDE | xargs -I{} mv {} $TARGET
alex.pilon
источник
Это лучшее решение для Busybox / ASH
Стюарт Кардалл
1
Это сработало для меня в ситуации, когда мне пришлось переместить все файлы, кроме нескольких папок, в другой каталог
Umar Hayat
-lВариант lsбудет включать в себя много неактуальной информации в командной строке и привести к выходу из строя команды мв.
jdhao
5

Следующее не является гарантированным на 100% методом, и его вообще не следует пытаться использовать для сценариев. Но иногда это достаточно для быстрого использования интерактивной оболочки. Файловый файл как

[abc]*

(который будет соответствовать всем файлам с именами, начинающимися с a, b или c) можно отменить, вставив сначала символ «^», т.е.

[^abc]*

Иногда я использую это для несоответствия директории lost + found, например:

mv /mnt/usbdisk/[^l]* /home/user/stuff/.

Конечно, если есть другие файлы, начинающиеся с l, я должен обработать их потом.

hlovdal
источник
4
mv `find Linux/Old '!' -type d | fgrep -v Tux.png` Linux/New

Команда find выводит список всех обычных файлов, а команда fgrep отфильтровывает любой Tux.png. Обратные галочки говорят mv переместить полученный список файлов.

Дэвид Норман
источник
4
Никогда, никогда не оценивайте find как аргументы для другой команды. Будут плохие вещи. Возможно, вы только что создали уязвимость. Всегда используйте find -print0 | Создайте xargs -0 или найдите -exec.
Juliano
3

Как насчет того, чтобы переместить все в папке, а затем просто переместить Tux.png обратно?

Я не могу придумать какой-либо синтаксис оболочки, чтобы сказать «все, кроме ...» от руки.

Дэвид З
источник
3
ls ~/Linux/Old/ | grep -v Tux.png | xargs -i {} mv ~/Linux/New/'
Aitor
источник
1
Эта команда, кажется, пропускает одну часть и не работает на моем компьютере. ls ~/Linux/Old/ | grep -v Tux.png | xargs -I{} mv {} ~/Linux/New/работает вместо
Кэтрин Чен,
3

Как насчет:

mv $(echo * | sed s:Tux.png::g) ~/Linux/New/

Вы должны быть в папке, хотя.

antibus
источник
3

Можно пропустить grep следующим образом:

ls ~/Linux/Old/ -QI Tux.png | xargs -I{} mv ~/Linux/Old/{} ~/Linux/New/
Arch Linux Tux
источник
1

Это может быть проще и легче запомнить, и это работает для меня.

mv $(ls ~/folder | grep -v ~/folder/exclude.png) ~/destination

Пакпум Тивакорнкит
источник