Запустите команду с пробелами в скрипте bash - PullRequest
2 голосов
/ 10 января 2011

У меня есть файл, который содержит список файлов:

02 of Clubs.eps
02 of Diamonds.eps
02 of Hearts.eps
02 of Spades.eps
...

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

while read -r line
do
    for i in 80 35 200
    do
        convert $(sed 's/ /\\ /g' <<< Cards/${line}) -size ${i}x${i} ../img/card/$(basename $(tr ' ' '_' <<< ${line} | tr '[A-Z]' '[a-z]') .eps)_${i}.png;
    done
done < card_list.txt

Однако это не работает, очевидно, пытаясь разбить каждое слово, что приводит к следующей ошибке:

convert: unable to open image `Cards/02\': No such file or directory @ error/blob.c/OpenBlob/2514.
convert: no decode delegate for this image format `Cards/02\' @ error/constitute.c/ReadImage/532.
convert: unable to open image `of\': No such file or directory @ error/blob.c/OpenBlob/2514.
convert: no decode delegate for this image format `of\' @ error/constitute.c/ReadImage/532.
convert: unable to open image `Clubs.eps': No such file or directory @ error/blob.c/OpenBlob/2514.

Если я изменю преобразование на эхо, результат будет выглядеть правильно, и если я сам скопирую строку и запусту ее в оболочке, она будет работать нормально:

convert Cards/02\ of\ Clubs.eps -size 80x80 ../img/card/02_of_clubs_80.png
convert Cards/02\ of\ Clubs.eps -size 35x35 ../img/card/02_of_clubs_35.png
convert Cards/02\ of\ Clubs.eps -size 200x200 ../img/card/02_of_clubs_200.png
convert Cards/02\ of\ Diamonds.eps -size 80x80 ../img/card/02_of_diamonds_80.png
convert Cards/02\ of\ Diamonds.eps -size 35x35 ../img/card/02_of_diamonds_35.png
convert Cards/02\ of\ Diamonds.eps -size 200x200 ../img/card/02_of_diamonds_200.png
convert Cards/02\ of\ Hearts.eps -size 80x80 ../img/card/02_of_hearts_80.png
convert Cards/02\ of\ Hearts.eps -size 35x35 ../img/card/02_of_hearts_35.png
convert Cards/02\ of\ Hearts.eps -size 200x200 ../img/card/02_of_hearts_200.png
convert Cards/02\ of\ Spades.eps -size 80x80 ../img/card/02_of_spades_80.png

UPDATE:

Просто добавление кавычек (см. Ниже) приводит к тому же результату, что и выше, где я использовал sed для добавления обратной косой черты

convert '"'Cards/${line}'"' -size ${i}x${i} ../img/card/$(basename $(tr ' ' '_' <<< ${line} | tr '[A-Z]' '[a-z]') .eps)_${i}.png;

Я пробовал как двойные, так и одинарные кавычки

Ответы [ 3 ]

3 голосов
/ 10 января 2011

Оболочка отлично работает с разделением строк и использованием переменных, чтобы сделать код читабельным, избегая здесь горизонтальных полос прокрутки ...

while read -r line
do
    for i in 80 35 200
    do
        epsfile="Cards/$line"
        pngbase=$(basename "$line" .eps | tr ' A-Z' '_a-z')
        pngfile="../img/card/${pngbase}_${i}.png"
        convert "$epsfile" -size ${i}x${i} "$pngfile"
    done
done < card_list.txt

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

Несмотря на то, что ограничение в 80 символов не является жестким, стоит сохранить его как грубое ограничение, посколькуесли строка намного длиннее, она, вероятно, не читается, а код должен быть читабельным, чтобы его можно было поддерживать.

2 голосов
/ 10 января 2011

Просто заключите в кавычки имена файлов с пробелами или другими специальными символами. Также Вам не нужен sed или tr.

См. Документацию bash по «Подстановке переменных» (стр. 21-22, ссылка на bash Pocket, О'Рейли)

Упростите цикл, поместив логику преобразования в функцию

# cvt file size 
cvt() {
 infile="$1"  # quote in case filename has blanks
 size="$2"
 outfile="${infile/ /_}"              # replace spaces with underlines
 outfile="${outfile##*/}"             # remove any directory path
 outfile="${outfile,,*}"              # downcase the filename
 outfile="${outfile%.eps}_$size.png"  # remove suffix, add size and new suffix
 ( set -x ; convert "Cards/$infile" -size ${size}x$size "../img/card/$outfile" )
}

while read -r line ; do
  for i in 80 35 200 ; do
    cvt "$line" $i
  done
done < card_list.txt
1 голос
/ 10 января 2011

Как сказал Хай, заключите имя вашего файла в "".В противном случае оболочка считывает пробел в строке как разделитель для следующего аргумента.

например.

VAR="test file"
cat $VAR # outputs the contents of 'test', followed by the contents of 'file'

cat "$VAR" # outputs the contents of 'test file'

edit: Короче говоря, ваша проблема заключается в использовании sed для выхода из пробелов.Он не делает то, что, как вы думаете, он делает - он производит буквальную строку «02 \ of \ Clubs.eps», а не «02 of Clubs.eps».Замените часть sed только "Cards / $ {line}".

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...