Перемещение файлов и запрос пользователю при наличии повторяющихся имен:
Как Subv3rsion - это и Эрика Лещински ответы показывают, что -newermt
предикат выбирает файлы, измененные более недавно, чем дата (и необязательное время), указанные в качестве его операнда. Чтобы найти файлы
- где-нибудь в
srcdir
(т.е. включая его подкаталоги, их подкаталоги и т.д.)
- последнее изменение (например) в сентябре 2014 года
-
и переместите их к
destdir
...ты можешь бежать:
find srcdir - тип f-newermt 2014-08-31 ! -newermt 2014-09-30-exec mv-i {} дестдир/ \;
В одном -exec
выражение, find передает имя файла, найденное вместо {}
. ;
означает, что -exec
что команда, которую нужно выполнить, и все ее аргументы были предоставлены (в случае, если последующие выражения передаются для поиска после этого конкретного -exec
аргументы предиката - см. Ниже пример этого). ;
должно быть экранировано как \;
таким образом, оболочка не интерпретирует его специально. (Без \
, ;
положил бы конец всему find
команда, работающая так же, как перевод строки. Даже несмотря на то, что это find
команда ничего не имеет после этого -exec
выражение, не сумев передать ;
аргумент по-прежнему является синтаксической ошибкой.)
Если вы просто хотите перечислить файлы - что желательно, если вы не уверены, как хранятся старые электронные письма или какие другие файлы могут присутствовать - опустите -exec
и все, что находится справа от него. (Для электронной почты часто электронные письма с разных дат хранятся в такой же файл; для тех, кто находится в ситуации, описанной в вопросе здесь, я рекомендую изучить, как они хранятся, прежде чем перемещать какие-либо файлы.) Если вы хотите одновременно напечатать их имена и переместить их, добавьте -print
до -exec
.
mv -i
запрашивает в любое время, когда файл будет перезаписан в месте назначения, например, если:
- файл с таким же именем существует из предыдущей резервной копии, или
- файл с тем же именем, но из другого подкаталога
srcdir
уже был перемещен в течение того же find
операция, или
-
(наименее вероятно) файл с таким же именем был создан где-то в
srcdir
в течение того же find
операция, после того как оригинал был перемещен, но достаточно скоро, чтобы его можно было найти один раз find
переходит в другой подкаталог.
Другие способы вызова mv
:
У вас есть другие варианты обработки файлов с повторяющимися именами.
- Без
-i
(т.е., mv {} дестдир/
), mv
обычно не запрашивает утверждение, но делает это, если конечный файл доступен только для чтения. (mv
иногда может даже получиться перезапись файла, доступного только для чтения, например, если файл принадлежит пользователю, который его запускает.)
- Если вы не хотите даже такой степени интерактивности и хотите
mv
всегда, чтобы (попытаться) перезаписать файлы с одинаковыми именами, используйте mv -f
.
- Если, напротив, вы хотите пропустить исходные файлы, когда уже есть целевой файл с тем же именем, используйте
mv -n
.
-
mv
принимает -b
и --backup
флаги для автоматического переименования файлов с одинаковыми именами, которые уже существуют в месте назначения. По умолчанию ~
добавляется для создания имени резервной копии, и если файл с таким именем и файл с именем резервной копии уже существуют в месте назначения, файл резервной копии перезаписывается. Это значение по умолчанию может быть переопределено параметрами, переданными при вызове mv
, а также переменными среды. Видеть man mv
для получения более подробной информации и приведенного ниже примера.
Перемещение файлов и создание резервных копий на случай дублирования имен:
Чтобы переместить все файлы, создайте резервные копии файлов с повторяющимися именами с помощью ~
суффикс и используйте пронумерованный .~n~
суффиксы, когда .~
файлы уже существуют (чтобы избежать перезаписи чего-либо), запустите:
find srcdir -type f -newermt 2014-08-31 ! -newermt 2014-09-30 -exec mv --backup=existing {} дестдир/ \;
Если вы пропустили файлы с повторяющимися именами и хотите узнать, какие из них:
Если вы используете mv -n
и хотите знать, какие файлы не были перемещены, потому что был другой файл с тем же именем, лучший способ, вероятно, просто запустить исходный find
командуйте снова, без -exec
и все, что находится справа от него. При этом будут напечатаны их имена.
Он также выведет имена всех соответствующих файлов, созданных с момента запуска исходного find .... -exec ...
команда, но для этого приложения, как правило, ее не будет, поскольку вы ищете файлы со старыми временами модификации. Можно присвоить файлу временную метку модификации, более старую, чем его реальный возраст, с touch
и другие механизмы, но, похоже, в данном случае это вряд ли произойдет без вашего ведома.
Зная сразу, как файлы пропускаются из-за повторяющихся имен:
mv -n
не сообщает и не возвращает никаких специальных код выхода, когда он воздерживается от перемещения файла. Поэтому, если вы хотите немедленно получать информацию о пропущенных файлах во время find
однако для этого вам придется сделать отдельный шаг. Один из способов - это:
find srcdir - тип f-newermt 2014-08-31 ! -newermt 2014-09-30-exec mv-n {} дестдир/ \; \ -exec [ -f {} ] \; -exec printf "\`%s' skipped (exists in \`%s')\\n" {} дестдир \;
Несколько, возможно, незначительных технических соображений: это неправильно предупреждает, если mv
не удается скопировать файл по причине, отличной от существующей в месте назначения и выходит сообщение об успехе. Это кажется маловероятным, но я не уверен, что это невозможно. Он также потенциально страдает от условия гонки: он будет предупреждать, когда реальной ошибки вообще нет, если новый файл с тем же именем был создан в том же месте в течение очень короткого времени после перемещения старого файла и перед проверкой, был ли он удален. (Учитывая приложение, я сомневаюсь, что любая из этих проблем когда-либо возникнет на самом деле.) Его можно было бы переписать, чтобы проверить пункт назначения до перемещение файла вместо after: тогда условие гонки будет относиться к вновь созданным файлам назначения, а не к исходным файлам. И в то время как ошибки и предупреждения, сообщаемые find
или mv
(или [
, хотя их и не должно быть) будет записано в стандартная ошибка, наш ...skipped (exists in...
предупреждение записывается на стандартный выход. Обычно оба они отображаются на вашем терминале, но это может иметь значение, если вы пишете сценарии.
Я разделил эту команду на две строки для удобства чтения. Его можно запустить таким образом, или вы можете удалить \
и новая строка (т.е. разрыв строки).
Как это происходит find
командная работа?
find
предикаты могут быть тесты (как -type
и -newermt
), используемые для их возвращаемых значений, или действия (как -print
и -exec
), которые являются часто используется из-за их побочных эффектов.
Когда нет оператора (например -a
для и, -o
для или) предоставляется между выражениями, -a
подразумевается. find
нанимать оценка короткого замыкания для и и или. p q
(т.е., p - а q
) верно только в том случае, если p и q выражения оба истинны, так что q не нужно оценивать, если p является ложным. Хотя мы часто не думаем об этом в этих терминах, именно поэтому тесты должны быть истинными для оценки последующих действий или тестов. Например, предположим, что find
натыкается на каталог. Он оценивает -type f
значение false, чтобы впоследствии он мог пропустить все.
Как и тесты, действия также оцениваются как истинные или ложные. Таким образом, -exec
сообщает, завершилась ли выполненная команда, сообщая об успешном выполнении (true) или сбое (false). У нас есть эта цепочка -exec
выражения, связанные с неявным и:
-exec mv -n {} дестдир/ \; -исполнитель [ -f {} ] \; -исполнитель printf "\`%s' пропущено (существует в \`%s')\\n" {} дестдир \;
Это попытается переместить файл, и если mv
сообщает о сбое, останавливается. Мы не хотим предупреждать о правильно пропущенном файле, если из-за какой-то другой проблемы он не был перемещен.
Но если это удалось, то затем он запускается то [
команда. Как find
, [
поддерживает свой собственный тип выражений, передаваемых в качестве аргументов. [ -f {} ]
проверяет, является ли операнд после -f
(передано ему по find
на месте {}
) существует (и является обычным файлом) и возвращает либо true/success, либо false/failure.
(Статусы выхода многих команд лучше всего интерпретировать как означающие успех или неудачу, но [
статус exist обычно лучше всего интерпретировать как true или false.)
Если [
возвращено значение false, тогда файл исчез, значит, он был перемещен, так что нет необходимости что-либо делать. Но если [
возвращено значение false, файл все еще там. Затем find
оценивает следующий -exec
выражение, которое выводит предупреждающее сообщение.
Дальнейшее чтение