#!/usr/bin/env bash
FILETYPES=( "*.html" "*.css" "*.js" "*.xml" "*.json" )
DIRECTORIES=`pwd`
MIN_SIZE=1024
for currentdir in $DIRECTORIES
do
for i in "${FILETYPES[@]}"
do
find $currentdir -iname "$i" -exec bash -c 'PLAINFILE={};GZIPPEDFILE={}.gz; \
if [ -e $GZIPPEDFILE ]; \
then if [ `stat --printf=%Y $PLAINFILE` -gt `stat --printf=%Y $GZIPPEDFILE` ]; \
then gzip -k -4 -f -c $PLAINFILE > $GZIPPEDFILE; \
fi; \
elif [ `stat --printf=%s $PLAINFILE` -gt $MIN_SIZE ]; \
then gzip -k -4 -c $PLAINFILE > $GZIPPEDFILE; \
fi' \;
done
done
此脚本使用gzip
压缩所有Web静态文件。当我尝试运行它时,我收到此错误bash: line 5: [: 93107: unary operator expected
。这个脚本出了什么问题?
答案 0 :(得分:3)
您需要导出MIN_SIZE
变量。你有find
spawn的bash没有它的值,所以脚本运行(正如我在@ ooga的回答中提到的那样)[ $result_from_stat -gt ]
这是一个错误(当结果时)是93107
)获取[ 93107 -gt ]
哪个(如果你在shell中运行)获得输出:
$ [ 93107 -gt ]
-bash: [: 93107: unary operator expected
答案 1 :(得分:2)
这可能更简单:
#!/usr/bin/env bash
FILETYPES=(html css js xml json)
DIRECTORIES=("$PWD")
MIN_SIZE=1024
IFS='|' eval 'FILTER="^.*[.](${FILETYPES[*]})\$"'
for DIR in "${DIRECTORIES[@]}"; do
while IFS= read -ru 4 FILE; do
GZ_FILE=$FILE.gz
if [[ -e $GZ_FILE ]]; then
[[ $GZ_FILE -ot "$FILE" ]] && gzip -k -4 -c "$FILE" > "$GZ_FILE"
elif [[ $(exec stat -c '%s' "$FILE") -ge MIN_SIZE ]]; then
gzip -k -4 -c "$FILE" > "$GZ_FILE"
fi
done 4< <(exec find "$DIR" -mindepth 1 -type f -regextype egrep -iregex "$FILTER")
done
pwd
。你可以$PWD
。也许你需要的是一个数组变量。find
的参数,而是通过进程替换从pipe
或更好地从已命名的pipe
读取输入。-ot
或-nt
。-f
)编写输出,则不需要>
,因为默认情况下该重定向形式会覆盖目标。find
,因为它更有效。您可以查看我如何制作过滤器并使用-iregex
。可能适用\( -iname one_ext_pat -or -iname another_ext_pat \)
也可以适用,但更难。exec
是可选的,以防止不必要地使用其他进程。[[ ]]
而不是[ ]
。4<
打开包含文件描述符4
的输入,-u 4
从该文件描述符中读取read
,而不是stdin (0)
。-ge MIN_SIZE
(大于或等于)-gt
。考虑一下,如果您的bash是4.0或更高版本,readarray
是一个更干净的选项:
for DIR in "${DIRECTORIES[@]}"; do
readarray -t FILES < <(exec find "$DIR" -mindepth 1 -type f -regextype egrep -iregex "$FILTER")
for FILE in "${FILES[@]}"; do
...
done
done