Я только что потерял небольшую часть своей аудиоколлекции из-за глупой ошибки, которую я сделал. :-(
Я рад, что у меня была сравнительно недавняя резервная копия, но она все еще раздражала. Помимо твоей правды, другим виновником был вред mv
, который будет выглядеть следующим образом:
Аудиофайлы имели определенную схему:
ARTIST - Some Title YY.mp3
где YY
указывается двухзначная годовая спецификация.
mkdir 90<invisible control character>
(До этого момента я не знал, что на самом деле набрал треть лишних символов, которые были невидимы ...!)
Вместо того, чтобы хранить все в одном каталоге, я хотел, чтобы вся музыка 1990-х годов была в одном каталоге. Поэтому я напечатал:
find . -name '* 9?.mp3' -exec mv {} 90 \;
Не так сложно понять, что случилось, а? : ->
Результатом (катастрофического) был пустой каталог с именем «90 что - то » (с чем-то, что является «невидимым» управляющим символом) и один единственный файл с именем «90», перезаписанный n раз.
ВСЕ ФАЙЛЫ Ушли. : - (((очевидно)
Желания mv
бы я проверил вовремя ли подпись «файл» назначения (помните о * NIX: Все это файл ) начинается с d------
(например drwxr-xr-x
). И, конечно же , является ли адресат существует вообще. Существует вариант вышеупомянутого сценария, когда вы просто забыли вmkdir
директорию первым. (но, конечно, вы предположили, что это там ...)
Даже наша ОС животное-ненависть , начиная с капиталом W Имеет ли это сделать. Вы даже получаете запрос указать тип места назначения (файл? Каталог?), Если вы попросите об этом.
Следовательно, мне интересно, если мы * NIXers все еще должны написать себе « mv
скриптлет», просто чтобы избежать подобных нежелательных сюрпризов.
.mp3
должен быть там с именем90
, это может быть тот, для которого у вас не было резервной копии.mv
здесь не проблема, технически, он не знает, что вы перемещаете ряд файлов. Вы запускаетеmv
один раз для каждого файла. Вот так иfind -exec ;
работает. Если бы вы использовалиfind -exec +
(как в некоторых комментариях) крикнулmv
бы , как только он получил более одного аргумента.mv
для каждого отдельного файла на первый взгляд может показаться немного менее продуманным, он (как я уже говорил ранее) будет единственным разумным решением, когда исходные файлы будут разбросаны по разным подкаталогам. То, что в моем тестовом примере исходные файлы были в одном каталоге, не означает, что это мой настоящий тестовый пример. На самом деле это просто упрощение, потому что позже я могу сам уточнить это самостоятельно. Плюс, это делает вопросы менее трудоемкими для чтения из-за их уменьшенной длины. :)mv
что пункт назначения существует?mv oldfile newfile
это способ переименовать файл, и глупо ожидать,newfile
что он уже существует и будет каталогом.Ответы:
Вы можете добавить
/
к месту назначения, если вы хотите переместить файлы в каталог. Если каталог не существует, вы получите сообщение об ошибке:Если каталог существует, он перемещает файл в этот каталог.
источник
В GNU coreutils
mv
уже есть опция, указывающая, что вы хотите перейти в каталог:-t
/--target-directory
. Если аргумент этой опции не существует,mv
будете жаловаться, вместо того, чтобы переместить все ваши файлы в одно и то же имя файла.Я бы написал ваш двигатель следующим образом:
Обратите внимание на использование
+
вместо того\;
, чтобы объединять как можно больше имен файлов, что приводит к более быстрому выполнению.источник
find . -name '* 9?.mp3' -exec sh -c 'exec mv "$@" 90/' sh {} +
Кроме того, если вы обычно планируете избежать случайных перезаписей в будущем, есть
-i
опция дляmv
. Я лично не могу думать о каких-либо недостатках, если выЕсли вам нужно что-то перезаписать, просто пропустите
-f
опцию.Псевдонимы вступают в силу только в том случае, если вы вводите команду непосредственно в интерактивную оболочку, а не в таких случаях, как вызов с помощью
find
. Вы могли бы бежатьи тогда вам будет предложено, если
mv
бы попытался перезаписать существующий файл.источник
mv
. Этот менее известный «трюк» приведет к тому, что команда с добавленной обратной косой чертой будет игнорировать любые определения псевдонимов.find ... -exec mv ...
, то вам нужно создать~/bin/mv
(или какой-то другой соответствующий каталог) и сделать это/bin/mv -i "$@"
- потомуfind ... -exec
что не смотрит на псевдонимы.env mv
. Меньше печатать. :) Поскольку моя локальная раскладка клавиатуры требует нажатия клавиши SHIFT для прямой косой черты, я всегда предпочел бы версии без косой черты (если применимо).mv
в каком-то месте в начале$PATH
было бы более чистым решением. С другой стороны,mv
в интерактивной оболочке я, как правило, небрежно отношусь (потому что это происходит быстро). В тот момент я сочиняю что - то более сложное, какfind
илиfor
цикл, или даже сценарий оболочки, я , как правило, выполнить некоторые сухие пробеги ( с помощьюecho
) , чтобы гарантировать , что я не нарушаю что - то. В этих случаях мне не нужно держать рукуmv
, потому что я уже вкладываю в нее некоторые мысли.В дополнение к превосходным ответам, приведенным выше, я хотел бы уточнить, почему вы не получили вопрос о том, перемещать файлы или нет.
Если вы переместите один файл с новым именем, и это имя не является каталогом,
mv
вы переименуете ваш файл на новое имя.Проблема заключается в том, что вы использовали
find
для выполненияmv
один раз для файла , а не один раз для всех файлов .Если вместо этого вы сделали
mv *90.mp3 90
, тоmv
не получилось бы с сообщением об ошибке «целевой файл не является каталогом».Другой совет - использовать завершение табуляции при вводе целевого пути. Он покажет вам, является ли цель каталогом, добавив
/
к имени цели. Вы также можетеmv -i
спросить, хотите ли вы перезаписать существующий файл.источник
mv *90.mp3 90
, то mv потерпел бы ошибку с сообщением об ошибке «целевой файл не является каталогом». Ха, да, почему так сложно, а? Я использую вашу линию, и я буду счастлив. Только в этом тривиальном случае. :) Потому что это нормальный способ задавать вопросы: для простоты я бы их сузил. Доfind
сих пор никто не возражал против того, что файлы 90-х годов также могут быть разбросаны по разным подкаталогам, которые я тоже хочу «поймать». Если и только если они всегда находятся в одном исходном каталоге, вашаmv
строка применима.mv
поведения, а не как критику вашего выбора инструментов.find
иmv
, например,find /music -type d -exec mv {}/*90.mp3 targetdir\;
- но теперь я чувствую, что я слишком усложняю это, и просто использую-i
или-t
более эффективноfind . -type d -exec mv {}/*9?.mp3 target \;
пример работал, все равно был бы риск, чтоmv
команда будет выглядетьmv file target
для каждого каталога, который содержит только один*9?.mp3
файл; поэтому все такие файлы (кроме последнего) будут потеряны.*.mp3
файлами в дереве каталогов, вы можете,shopt -s globstar
а затем запустить свою команду**/*.mp3
- the**
будет действовать как afind
.В качестве альтернативы универсальной стратегии я хотел бы предложить превратить эту операцию во временный сценарий. Я предпочитаю смотреть на результаты
find
и превращать их вmv
команду вручную, гарантируя, что я понимаю, что я делаю, прежде чем выполнить. например.Теперь я могу просмотреть список имен файлов и переписать содержимое файла в виде команды оболочки.
ggVGJ
Imv
[esc]
Asomedir/
[esc]
source tmp
в командной строке.Это консервативная стратегия, но меня слишком часто укусили опечатки
-exec
илиsed
команды, или неправильно понятые расширения оболочки, и я предпочитаю использовать медленный последовательный подход.Другими словами: я слишком труслив, чтобы использовать
-exec
.источник
:%s/.*/"&"/
шаг - потому что в этом случае вы знаете, что каждое имя файла содержит хотя бы один пробел.echo mv
вместоmv
, а затем удаление,echo
если вы счастливы.Другой вариант:
это то же самое, что -i, но оно не спросит, оно потерпит неудачу.
источник