2015-03-19 1 views
0

несколько дней назад я начал небольшой скрипт bash, который должен суммировать количество страниц и размер файла всех PDF-файлов в папке. Сейчас он работает хорошо, но я все еще не понимаю. Почему sed всегда терпит неудачу, если установлено shopt -s nullglob? Кто-нибудь знает, почему это происходит? Я работаю с GNU Bash 4.3 и sed 4.2.2 в Ubuntu 14.04.Bash: sed не работает, когда «shopt -s nullglob» установлен

set -u 
set -e 

folder=$1 

overallfilesize=0 
overallpages=0 
numberoffiles=0 

#If glob fails nothing should be returned 
shopt -s nullglob 

for file in $folder/*.pdf 
do 

    # Disable empty string if glob fails 
    # (Necessary because otherwise sed fails ?:|) 
    #shopt -u nullglob 

    # This command is allowed to fail 
    set +e 
    pdfinfo="$(pdfinfo "$file" 2> /dev/null)" 
    ret=$? 
    set -e 

    if [[ $ret -eq 0 ]] 
    then 
    #Remove every non digit in the result 
    sedstring='s/[^0-9]//g' 
    filesize=$(echo -e "$pdfinfo" | grep -m 1 "File size:" | sed $sedstring) 
    pages=$(echo -e "$pdfinfo" | grep -m 1 "Pages:" | sed $sedstring) 

    overallfilesize=$(($overallfilesize + $filesize)) 
    overallpages=$(($overallpages+$pages)) 
    numberoffiles=$(($numberoffiles+1)) 
    fi 

done 

echo -e "Processed files: $numberoffiles" 
echo -e "Pagesum: $overallpages" 
echo -e "Filesizesum [Bytes]: $overallfilesize" 

ответ

2

Вот простой тест для воспроизведения вашей проблемы:

#!/bin/bash 
shopt -s nullglob 
pattern='s/[^0-9]//g' 
sed $pattern <<< foo42 

Ожидаемый результат:

42 

Фактический выход:

Usage: sed [OPTION]... {script-only-if-no-other-script} [input-file]... 
(sed usage follows) 

Это происходит потому, что s/[^0-9]//g является действительный glob (соответствующий структуре, подобный структуре s/c/g), и вы попросили bash интерпретировать его. Так как у вас нет соответствующего файла, nullglob запускает и полностью удаляет шаблон.

Двойной процитировать предотвращает разбиение слов и Глоб интерпретация, которая почти всегда то, что вы хотите:

#!/bin/bash 
shopt -s nullglob 
pattern='s/[^0-9]//g' 
sed "$pattern" <<< foo42 

Это дает ожидаемый результат.

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

+0

То же самое можно сказать и о 'failglob' shopt. Ваш тестовый пример также подходит для этого. –