2013-09-22 2 views
2

Я пытаюсь перечислить все файлы PDF в заданном каталоге $1 (и его подкаталоги), получить количество страниц в каждом файле и вычислить два числа с помощью pagecount. Мой скрипт работал, но только на имена файлов, которые не содержат пробелов и только в одном каталоге, который заполнен только файлами PDF. Я уже немного изменил его (используя кавычки вокруг переменных и т. Д.), Но теперь я немного застрял.bash использует только первую запись из find

Проблема, с которой я столкнулась, заключается в том, что, как и сейчас, скрипт обрабатывает только первый файл, найденный find . -name '*.pdf'. Как я буду обрабатывать остальные?

#!/bin/bash 

wd=`pwd` 
pppl=0.03 #euro 
pppnl=0.033 #eruo 

cd $1 
for entry in "`find . -name '*.pdf'`" 
do 
     filename="$(basename "$entry")" 
     pagecount=`pdfinfo "$filename" | grep Pages | sed 's/[^0-9]*//'` 
     pricel=`echo "$pagecount * $pppl" | bc` 
     pricenl=`echo "$pagecount * $pppnl" | bc` 
     echo -e "$filename\t\t$pagecount\t$pricel\t$pricenl" 
done 

cd "$wd" 

ответ

1

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

Для устранения этой проблемы использовать время цикл вместо этого, как это:

find . -name '*.pdf' -print0 | while IFS= read -r -d '' entry 
do 
    .... 
done 

Прочитайте эту статью для более подробного обсуждения: http://mywiki.wooledge.org/ParsingLs

+0

Спасибо за ваш вклад, который отлично работает! – Simon

1

Это плохая идея использовать слово расщепление. Вместо этого используйте цикл while.

while read -r entry 
do 
     filename=$(basename "$entry") 
     pagecount=$(pdfinfo "$filename" | grep Pages | sed 's/[^0-9]*//') 
     pricel=$(echo "$pagecount * $pppl" | bc) 
     pricenl=$(echo "$pagecount * $pppnl" | bc) 
     echo -e "$filename\t\t$pagecount\t$pricel\t$pricenl" 
done < <(exec find . -name '*.pdf') 

предпочитают также $() над backticks, когда это возможно. Вам также не нужно размещать около "" переменные или подстановки команд, когда они используются для назначения.

filename=$(basename "$entry") 

А может просто быть просто

filename=${entry##*/} 
+0

Почему 'exec find'? – user000001

+1

@ user000001 Он предотвращает ненужный дополнительный подпроцесс. Просто то, что я изобрел и, вероятно, не знаю никому. – konsolebox

+0

Не могли бы вы подробнее рассказать об «exec find» и о различии между '$()' и 'backticks'? Я совершенно новичок в этом. Благодаря! – Simon

Смежные вопросы