BASH dirname basename 有空格的问题
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/29505788/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
BASH dirname basename problems with spaces
提问by jmituzas
Writing a script to optimize my images for the web. Having issues with filenames and directories with spaces in the names.
编写脚本来优化我的网络图像。文件名和名称中带有空格的目录有问题。
Heres what I have:
这是我所拥有的:
read -p "Enter full path from root (/) to your site... example /var/www/public_html: " path1
echo ""
#read -p "Enter in ImageMagick quality (default is 80) if unsure enter 80: " optjpg
#echo ""
#id="$(id -u optiimage)"
cmd="id -u optiimage"
eval $cmd
id=$(eval $cmd)
tmp1="${path1}/shell/optiimage/imagemagick"
tmp2="${path1}/shell/optiimage/imagemagick/jpg"
restore1="${path1}/shell/optiimage/restore"
restore2="${path1}/shell/optiimage/restore/imagemagick/jpg"
backup1="${path1}/shell/optiimage/backup"
backup2="${path1}/shell/optiimage/backup/imagemagick/jpg"
log1="${path1}/shell/optiimage/log/imagemagick/"
DATE="$(date +%a-%b-%y-%T)"
# Need user input for www path from root
##
## Make directories
##
############################################################################################################
mkdir -p ${tmp1}
mkdir -p ${tmp2}
mkdir -p ${restore1}
mkdir -p ${restore2}
mkdir -p ${backup1}
mkdir -p ${backup2}
mkdir -p ${log1}
mkdir -p ${path1}/build
echo "Processing JPG Files"
find $path1 -iname "*jpg" | \
#write out script to put on cron for image optimization
while read file;
do
# If not equal to optimage uid
# to check username id -u optimage
if [ -u "${id}" ]; then
filebase=`basename "$file" .jpg`
dirbase=`dirname "$file"`
echo "${dirbase}/${filebase}.jpg already optimized" >> ${log1}_optimized_$DATE.log
else
#simple log for size of image before optimization
ls -s $file >> ${log1}_before_$DATE.log
#Do the following if *.jpg found
filebase=`basename $file .jpg`
dirbase=`dirname $file`
echo "cp -p ${dirbase}/${filebase}.jpg ${tmp2}" >> ${path1}/build/backup_jpg.txt
echo "chown optiimage:www-data ${filebase}.jpg" >> ${path1}/build/restore_jpg.txt #${restore1}/imagemagick.sh
echo "cp -p ${filebase}.jpg ${dirbase}/${filebase}.jpg" >> ${path1}/build/restore_jpg.txt #${restore1}/imagemagick.sh
##
## ImageMagick
## Original Command:
## convert $file -quality 80 ${filebase}.new.jpg
##########################
echo "convert ${dirbase}/${filebase}.jpg -quality 80 ${tmp2}/${filebase}.jpg" >> ${path1}/build/imagemagick.txt
echo "mogrify -strip ${tmp2}/${filebase}.jpg" >> ${path1}/build/imagemagick.txt
echo "chown optiimage:www-data ${tmp2}/${filebase}.jpg" >> ${path1}/build/owner_jpg.txt
echo "rm ${dirbase}/${filebase}.jpg" >> ${path1}/build/remove_jpg.txt
echo "cp -p ${tmp2}/${filebase}.jpg ${dirbase}/" >> ${path1}/build/migrate_jpg.txt
simple log for size of image after optimization
优化后图像大小的简单日志
ls -s $file >> ${log1}_after_$DATE.log
fi
done
I have edited this with suggestions some have given me. It didn't seem to work. This works fine if I remove directories with spaces in the names otherwise it ends the name at the space and get errors directory doesn't exist.
我根据一些人给我的建议对其进行了编辑。它似乎不起作用。如果我删除名称中带有空格的目录,这会正常工作,否则它会在空格处结束名称并获取错误目录不存在。
回答by bgoldst
- You need to double-quote variable substitutions. This applies inside command substitutions as well as in the top-level lexical context. The only exception to this is assignment of a string variable from another string variable, e.g.
str2=$str1;
, although other types of variable assignments generally need quoting, such as assigning a string variable from an array slice, even if it only slices one element, e.g.str="${@:1:1}";
. - Although unlikely to be a problem here, the
read
builtin strips leading and trailing whitespace if you provide one or moreNAME
s; you can solve that by not providing anyNAME
s at all, and just letting it store the whole line in the$REPLY
variable by default. - You should always use the
-r
option of theread
builtin, as that prevents its ill-advised default behavior of doing backslash interpolation/removal on the input data. - If you don't need any kind of interpolation in a string literal, prefer the
'...'
syntax to"..."
, as the former does not do any interpolation. - Prefer the
[[ ... ]]
expression evaluation form to the old-style[ ... ]
form, as the former syntax is slightly more powerful. - Prefer the
$(...)
command substitution form to the old-style`...`
form, as the former syntax has more favorable nesting properties (namely, no need to escape the nested command substitution delimiters).
- 您需要双引号变量替换。这适用于内部命令替换以及顶级词汇上下文。唯一的例外是从另一个字符串变量分配字符串变量,例如
str2=$str1;
,尽管其他类型的变量分配通常需要引用,例如从数组切片分配字符串变量,即使它只对一个元素进行切片,例如str="${@:1:1}";
。 - 虽然在这里不太可能成为问题,但
read
如果您提供一个或多个NAME
s ,则内置会删除前导和尾随空格;您可以通过根本不提供任何NAME
s来解决这个问题,而只是让它$REPLY
默认将整行存储在变量中。 - 您应该始终使用内置
-r
选项read
,因为这可以防止其对输入数据进行反斜杠插值/删除的不明智的默认行为。 - 如果您不需要在字符串文字中进行任何类型的插值,则更喜欢使用
'...'
语法"..."
,因为前者不进行任何插值。 [[ ... ]]
与旧式[ ... ]
形式相比,更喜欢表达式求值形式,因为前者的语法稍微强大一些。- 更喜欢
$(...)
命令替换形式而不是旧式`...`
形式,因为前者的语法具有更有利的嵌套属性(即,无需转义嵌套的命令替换分隔符)。
find "$path1" -iname '*jpeg'| \
# write out script to put on cron for image optimization
while read -r; do
file=$REPLY;
# If not equal to optimage uid
# to check username id -u optimage
if [[ -u "$id" ]]; then
filebase=$(basename "$file" .jpeg);
dirbase=$(dirname "$file");
#MYBASENAME=$(basename "")
echo "${dirbase}/${filebase}.jpeg already optimized" >>"${log1}_optimized_$DATE.log";
fi;
done;
;
回答by higuaro
Quote your $file
variable in every place where is used:
$file
在每个使用的地方引用你的变量:
find $path1 -iname "*jpeg" | \
while read file;
do
if [ -u "${id}" ]; then
filebase=`basename "$file" .jpeg`
dirbase=`dirname "$file"`
fi
done