Как скопировать все файлы в папке, кроме файлов, которые записываются?

12

Я загружаю несколько файлов в папку downloadingчерез HTTPie . Сценарий bash предназначен для обработки загруженных файлов, и я попытался скопировать загруженные файлы в другую папку как

find /folder/downloading -type f -exec mv '{}' /folder/downloaded \;

но это также копирует файлы, которые еще не были закончены. Я пытался ограничить передачу старых файлов, добавив -mmin +5в команду. Какая эффективная команда оставить файлы пишутся и передавать только загруженные файлы?

Googlebot
источник
Если вы копируете в ту же файловую систему, и вы устанавливаете загрузчик, чтобы не переименовывать (загрузка в %.partзатем переименовать в%) Затем, если загрузчик ведет себя хорошо (ничего более странного не делает), вы должны иметь возможность переименовывать ( mv) файлы.
ctrl-alt-delor
1
Какую обработку вы пытаетесь сделать? Скорее всего, есть гораздо более простой вариант, например, использование конвейера.
садовник

Ответы:

11

Не очень эффективно, но вы могли бы сделать:

find /folder/downloading -type f -exec sh -c '
  for file do
    lsof -F a "$file" | grep -q w || mv "$file" /folder/downloaded
  done' sh {} +

То есть проверка , что файл не указан в списке с wобрядовым aрежимом ступы в lя sт oперо fИльза перед тем mо vING.

psmiscРеализация , fuserкак правило , находятся на Linux операционных систем на основе имеет -wфункцию (для проверки файлов открыть для записи) , но , к сожалению, только работу с -kубить соответствующие процессы. Тем не менее, кажется, что вы все еще можете использовать его, используя псевдосигнал 0, который ничего не делает:

find /folder/downloading -type f -exec sh -c '
  for file do
    fuser -s -w -k -0 "$file"  || mv "$file" /folder/downloaded
  done' sh {} +

Удалите -s(или даже замените его -v), если вы хотите увидеть, какой процесс (процессы) препятствует перемещению.

Обратите внимание, что если вы не запускаете эти команды как суперпользователь, вы получите только информацию о своих процессах. Если процессы, загружающие файлы, работают от имени другого пользователя, они останутся незамеченными.

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

Однако, в зависимости от того, для чего они были предназначены впоследствии, они могут быть сбиты с толку, если после того, как они закончат запись, файла больше не будет (например, если они захотят изменить некоторые атрибуты файла после его загрузки и не через дескриптор файла (как chmod()vs fchmod(), или utimes()который не может быть сделан через дескриптор файла)).

Стефан Шазелас
источник
Оболочка вопрос: я думаю, что я понимаю ваш код с одним исключением. Оператор -execзапускается shс одной командой ( -c '...'), и {} +он сообщает, что одновременно нужно вводить в эту команду более одного результата. Чего я не понимаю, так это того, почему shпосле команды есть еще один . Что мне не хватает?
Джо
2
@ Джо, вот что входит в состав встроенного сценария $0. То есть он дает имя этому встроенному скрипту. Это имя может использоваться в сообщениях об ошибках, таких как, <name>: fuser: command not foundнапример, поэтому, shкак правило, в этом случае хорошим выбором будет прояснить, что сообщает об этом сообщении об ошибке (это также будет, если мы вообще не приводим никаких аргументов после рядный скрипт).
Стефан