我是bash的新手,我正在编写遍历tar.gz文件存档的脚本,并在每个文件中更改指定给另一个字符串的字符串。脚本的参数:归档的名称,搜索的字符串,目标词。
我的问题是当存档名称包含空格时(例如我运行带有以下args的脚本:> change_strings.sh" /tmp/tmp.m7xYn5EQ2y/work/data txt" a A)我有以下错误:
在行if [ ! -f $filename ] ; then
[:data:二元运算符期望,dirname:额外的操作数`txt'。
这是我的代码:
#!/bin/bash
filename="${1##*/}"
VAR="$1"
DIR=$(dirname ${VAR})
cd "$DIR"
if [ ! -f $filename ] ; then
echo "no such archive" >&2
exit 1
fi
if ! tar tf $filename &> /dev/null; then
echo "this is not .tar.gz archive" >&2
exit 1
fi
dir=`mktemp -dt 'test.XXXXXX'`
tar -xf $filename -C $dir #extract archive to dir
cd $dir #go to argument directory
FILES=$dir"/*"
for f in $FILES
do
sed -i "s/$2/$3/g" "$f"
done
tar -czf $filename * #create tar gz archive with files in current directory
mv -f $filename $cdir"/"$filename #move archive
rm -r $dir #remove tmp directory
答案 0 :(得分:1)
处理此问题的正确方法是用双引号括住变量。
var=/foo/bar baz
CMD $var # CMD /foo/bar baz
上面的代码将在/ foo / bar和baz
上执行CMDCMD "$var"
这将在“/ foo / bar baz”上执行CMD。在大多数地方,最好用双引号括起变量。
答案 1 :(得分:1)
欢迎来到stackoverflow!
为了方便当前和未来的读者,这里有small, self contained example显示问题:
filename="my file.txt"
if [ ! -f $filename ]
then
echo "file does not exist"
fi
以下是我们获得的输出:
$ bash file
file: line 2: [: my: binary operator expected
这是我们期望获得的输出:
file does not exist
为什么他们不一样?
以下是shellcheck对此的评价:
$ shellcheck file
In file line 2:
if [ -f $filename ]
^-- SC2086: Double quote to prevent globbing and word splitting.
事实上,如果我们加倍引用它,我们得到预期的输出:
$ cat file
filename="my file.txt"
if [ ! -f "$filename" ]
then
echo "file does not exist"
fi
$ bash file
file does not exist
你应该是double quoting all your variables。
但是,您必须注意$FILES
,因为它包含您想要展开的glob /通配符以及您不希望使用wordsplit的潜在空格。最简单的方法是不要将它放在一个变量中,而是写出来:
for f in "$dir"/*
do
...