Ожидайте нескольких файлов, которые будут закончены, загружая

Установка Locale не является функцией рабочего стола GNOME3. Необходимо установить локаль в Операционной системе. man locale.

4
19.09.2013, 02:06
4 ответа

существует много проблем в Вашем сценарии, начиная с:

folder1="path-to-folder"
cd $folder1
while file=$(ls "$folder1") ...

это действительно делает cd path-to-folder; ls path-to-folder; если path-to-folder является абсолютным (запускающийся с '/' как в Вашем примере), это могло бы работать, но он не будет работать каждый раз, когда Вы используете относительные пути. это не будет также работать если path-to-folder содержит пробелы, поскольку необходимо использовать кавычки везде, например. cd "$folder1"

затем выполнение a while file=$(ls ...) сделает бесконечный цикл, как file будет всегда устанавливаться на что-то (содержание каталога).

правильный синтаксис был бы for file in $(ls ...), который прекратит работать, как только у Вас есть имена файлов с пробелами (поскольку цикл будет работать foo и bar если Вам назвали файл foo bar). проверьте, почему Вы никогда не должны анализировать вывод ls. вместо использования ls Вы могли просто сделать for file in *.

наконец, у Вас могли быть файлы, которые изменяются, даже если там размер не изменяется еще.

хороший способ выполнить итерации по файлам find команда; хороший способ проверить, изменилось ли что-то, mtime из файла.

следующая функция дает Вам значение для последнего изменения (mtime) любого файла в данном каталоге

folder1="/path-to-folder"
find "${folder1}" -exec stat -c "%Y" \{\} \;    \
   | sort -n | tail -1

таким образом, Ваш сценарий мог быть похожим:

#!/bin/bash
dir="$1"
# check whether $dir exists
test -d "${dir}" || exit 1

last=0
current=1

while [ "$last" != "$current" ]; do
   last=$current
   current=$(find "${dir}" -exec stat -c "%Y" \{\} \; \
             | sort -n | tail -1)
   sleep 10
done
echo "directory is now stable..."

ОБНОВЛЕНИЕ

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

while true; do
 for file_ready in *.copyfinished; do
   file=${file_ready%.copyfinished}
   if [ -e "${file}.converted" ]; then
      echo "skipping already converted file ${file}" 1>&2
   else
      touch "${file}.converted"
      do_convert "${file}"
   fi
 done
 sleep 1
done

это решение, очевидно, требует сотрудничества от передающей стороны.

4
27.01.2020, 20:51
  • 1
    Не анализируйте вывод ls. Кроме того, Вы сбиваете с толку for и while в середине — идиома для цикличного выполнения по файлам в каталоге for file in *; do ……. –  Gilles 'SO- stop being evil' 19.09.2013, 02:05
  • 2
    @Gilles точно; однако я не знаю, почему Вы добавили комментарий 'ls' часть к моему ответу, поскольку я уже упомянул тот парсинг ls доставит неприятности (хотя я не потрудился добавлять ссылку к более полному обсуждению). я зафиксирую while/for –  umläute 19.09.2013, 10:43
  • 3
    @umläute проблемы - Вы, предлагают сравнить размер папки вместо размера файлов в нем? –  ispasov 19.09.2013, 10:48
  • 4
    не, я предлагаю выдержать сравнение modification time из всех файлов в каталоге. (существует даже объяснение, почему я считаю сравнение размеров плохой идеей). –  umläute 19.09.2013, 10:50
  • 5
    Остерегайтесь этого stat -t \{\} | cut -d' ' -f13 перестанет работать, если имя файла будет содержать пробелы. Использовать stat -c "%Y" \{\} вместо этого (также легче ввести и отладить) –  ndemou 13.04.2015, 16:25

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

Отправьте файл во временное имя или каталог. Когда отправление закончено, перемещают файл в корректное местоположение

cp srcvideo.avi /folder1/srcvideo.tmp && mv /folder1/srcvideo.tmp /folder1/srcvideo.avi

Затем Ваш сценарий не должен делать всего тестирования на размерах. Это может просто ожидать корректного файла.

cd /folder1 || exit 1
for file in *.avi; do
  echo "$file found"
  do_some_processing "$file"
done

Вы могли достигнуть того же при помощи отдельного каталога передачи, не изменяя имена файлов, если Вы желаете.

2
27.01.2020, 20:51
  • 1
    Хорошо я не человек, который отправляет файлы. Также они отправляются от Windows PC. Мне нужно решение на моей стороне процесса как получатель. –  ispasov 19.09.2013, 09:40
  • 2
    Можно все еще определить спецификацию передачи для них. Иначе, чтобы они передали 0-байтовый файл в конце ${filename.done} то, что Вы опрашиваете относительно. –  Matt 19.09.2013, 11:36

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

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

Если Вы застреваете с некоторым нижним методом загрузки, используйте средство уведомления для реакции, когда файл закончил загружать, вместо того, чтобы вручную наблюдать файл. На Linux средство уведомления является inotify. В зависимости от того, как работает программа загрузки, любой реагирует на закрытие файла (если программа загрузки непосредственно пишет в заключительный файл), или в переименовывание (если программа загрузки сначала пишет во временный файл, затем переименовывает его в место).

Можно использовать инструмент оболочки inotifywait реагировать, когда событие файла происходит. Вот пример, который преобразовывает каждый переименованный файл.

cd /path/to/directory
inotifywait -m -e moved_to --format=%f . |
while IFS= read -r filename; do
  conversion-program "$filename"
done
1
27.01.2020, 20:51

Если Вы хотите запустить свой сценарий перед знанием, там ли все файлы, первая вещь состоит в том, чтобы проверить, является ли количество файла постоянным. Вы могли сделать что-то как, с помощью listfile = $(ls "$folder")

[ $( echo $listfile | wc -w) != $(ls "$folder" | wc -w) ]

в некоторое время цикле; пока вещь не равна, Ваш сброс $listfile кому: $(ls "$folder"). После того как это сделано, можно просто сделать a doцикл на $listfile где Вы делаете точно, что Вы делали на одном файле; после того как это сделано, можно запустить преобразование.

0
27.01.2020, 20:51
  • 1
    , Этот подход подвержен условиям состязания, особенно при передаче больших файлов. Кроме того, echo в echo $(ls "$folder") | wc -w избыточно. ls "$folder" | wc -w достаточно. –  Thomas Nyman 18.09.2013, 14:21

Теги

Похожие вопросы