Почему мой цикл иногда не читает всю строку? - PullRequest
3 голосов
/ 03 июля 2019

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

Это на машине с Debian 9 (bash). Я перепробовал множество способов написать цикл, включая конвейеризацию в файл (который получается правильным) и затем считывание его обратно в цикл (который затем смешивает мой вывод). Я попытался установить -x из первой строки скрипта, и это определенно является проблемой самой оболочки. Результаты также различаются. Иногда я помещаю файл и получаю 30 символов, иногда он читает только 22, но это всегда одни и те же файлы, которые терпят неудачу. od -xa показывает, что между ними нет неправильных символов.

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

PPATH="/home/pi/pmount/prntest"

find "$PPATH" -type f -iname "*.mp4" >tempfile

cat -v tempfile | while read i
do
makethumbs "$i"
echo "$i" >>test.txt
done

например. путь к файлу /home/pi/pmount/prntest/Security Training/Example #1.mp4

Пример вывода:

/prntest/Security Training/Example #1.mp4

или

urity Training/Example #1.mp4`

Конечно, это не может быть проанализировано. Есть идеи? Я был бы очень благодарен.

EDIT:

Обязательная информация:

Shell: /bin/bash 

GNU bash, Version 4.4.12(1)-release (x86_64-pc-linux-gnu) Copyright (C) 2016 Free Software Foundation, Inc. 

Linux 4.9.0-9-amd64 #1 SMP Debian 4.9.168-1+deb9u3 (2019-06-16) ``` 

Ответы [ 2 ]

2 голосов
/ 03 июля 2019

Желательно выводить нулевые $'\0' завершенные записи, а не символ новой строки $'\n'.Параметр -print0 команды find делает именно это.

Вот ваш исправленный код:

#!/usr/bin/env bash

PPATH=/home/pi/pmount/prntest

find "$PPATH" -type f -iname "*.mp4" -print0 >tempfile # write null-terminated strings to tempfile

while read -r -d '' i # -r do not expand globbing characters and -d '' use a null delimiter
do
  makethumbs "$i"
  echo "$i" >>test.txt
done <tempfile # inject the tempfile for the whole loop
1 голос
/ 03 июля 2019

При обнаружении записи в файл только для немедленного чтения это не нужно.Кроме того, почему cat -v?

Я бы сделал это:

find "$PPATH" -type f -iname "*.mp4" -print -exec makethumbs {} ';' | tee test.txt

ОК, makethumbs - это функция оболочки.Тем не менее можно придерживаться этого подхода:

export -f makethumbs 
find "$PPATH" -type f -iname "*.mp4" -print -exec bash -c '
    for file; do makethumbs "$file"; done
' _bash {} + | tee test.txt

Использование формы -exec cmd {} + для одновременной передачи нескольких файлов в команду, чтобы минимизировать количество вызываемых оболочек bash.

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

Аргумент "_bash" необходим, поскольку при передаче аргументов при использовании опции -c первый аргумент принимается за $0

...