Фильтрация скрытых файлов с помощью Bash (для сценария изменения размера пакетного изображения) - PullRequest
1 голос
/ 16 ноября 2009

Я пишу скрипт для пакетного изменения размеров изображений. Первоначально я применял операцию for file in $(ls $1), но я хотел бы иметь возможность использовать глобирование, поэтому я смотрю на что-то более похожее на for file in $(echo $1). Проблема в том, что dotglob может включаться или не включаться, поэтому echo * может возвращать скрытые файлы (в частности, .DS_Store), в результате чего convert выдает ошибку и останавливает скрипт. Мне бы хотелось, чтобы стандартное поведение команды было , что если я cd войду в каталог, полный изображений и выполню resize * 400x400 jpg, все изображения будут изменены , исключая скрыто файлы, независимо от того, включен ли dotglob.

Итак, в псевдокоде Я ищу :

for file in $(echo $1 | [filter-hidden-files])

Вот мой скрипт с старым поведением . Будет обновляться с новым поведением, когда я найду решение:

# !/bin/bash

# resize [folder] [sizeXxsizeY] [outputformat]
# if [outputformat] is omitted, the input file format is assumed

for file in $(ls $1)
do
    IMGNAME=$(echo "$file" | cut -d'.' -f1)
    if test -z $3
    then
        EXTENSION=$(echo "$file" | cut -d'.' -f2)
        convert $1/$file -resize $2 -quality 100 $1/$IMGNAME-$2.$EXTENSION
        echo "$file => $IMGNAME-$2.$EXTENSION"
    else 
        convert $1/$file -resize $2 -quality 100 $1/$IMGNAME-$2.$3
        echo "$file => $IMGNAME-$2.$3"
    fi
done

Вот текущий скрипт:

# !/bin/bash

# resize [pattern] [sizeXxsizeY] [outputformat]
# if [outputformat] is omitted, the input file format is assumed

for file in $(echo $1)
do
        IMGNAME=$(echo "$file" | cut -d'.' -f1)
        if test -z $3 && if test -f $3
        then
            EXTENSION=$(echo "$file" | cut -d'.' -f2)
            convert $file -resize $2 -quality 100 $IMGNAME-$2.$EXTENSION
            echo "$file => $IMGNAME-$2.$EXTENSION"
        else 
            convert $file -resize $2 -quality 100 $IMGNAME-$2.$3
            echo "$file => $IMGNAME-$2.$3"
        fi
done

Учитывая команду resize * 400x400, convert выдает ошибку, так как не может обработать .DS_Store (скрытый файл, находящийся в каждом файле в системе OSX). Поскольку я никогда не буду обрабатывать скрытые изображения, я хотел бы автоматически их фильтровать. Я пытался сделать это с помощью grep или find, но пока не понял.

Новый скрипт идет сюда:

for file in $(echo $1)
do

Ответы [ 4 ]

3 голосов
/ 16 ноября 2009

Я бы предложил изменить командную строку вашего скрипта с resize * 400x400 на resize 400x400 *, таким образом скрипт будет больше похож на стандартные инструменты Unix (grep, sed, ln и т. Д.). Вам не нужно было бы отменять опцию dotglob в вашем скрипте (что лучше, так как это зависит от пользователя скрипта, если он хочет скрыть скрытые файлы или нет).

Ваш скрипт будет выглядеть примерно так:

#!/bin/bash

OUTPUTFORMAT=$1
# Remove original $1 from the list of arguments
shift

for i in "$@"
do
    # Use $OUTPUTFORMAT here
    etc....

Если вы не хотите изменять командную строку для вашего скрипта. Вы можете попробовать установить GLOBIGNORE

export GLOBIGNORE=".*"

Или, если установлено extglob, вы можете попробовать выполнить подкачку файла следующим образом:

echo !(.*)
1 голос
/ 16 ноября 2009

когда вы получаете список файлов в $ *, вы можете проверить их один за другим

for i in $*
do 
   expr $i : '^\..*' > /dev/null && continue
   # process file
done
1 голос
/ 16 ноября 2009

нет необходимости использовать ls с циклом for, большую часть времени это бесполезно. также цикл for с * не возвращает скрытые файлы, если вы не укажете это. Чтобы показать скрытые файлы,

for files in .*
do
 echo $files
done
1 голос
/ 16 ноября 2009

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

shopt dotglob

Вы также можете явно отключить его в своем скрипте:

#!/bin/bash

shopt -u dotglob

for file in $1/*; do
  ...
done
...