2014-10-26 3 views
0

Я новичок в bash, и я работаю над скриптом, который проходит файл tar.gz, и в каждом файле изменяется строка, указанная для другой строки. Арги сценария: имя архива, искомая строка, целевое слово. Моя проблема заключается в том, что когда имя архива содержит пробел (например, я запускаю скрипт со следующими аргументами:> change_strings.sh "/tmp/tmp.m7xYn5EQ2y/work/data txt" a A) У меня есть следующая ошибка: on line if [ ! -f $filename ] ; then [ : data: ожидается бинарный оператор, dirname: дополнительный операнд `txt '. Вот мой код:Пробелы в имени каталога Bash

#!/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 
+1

КРОССПОСТИНГ: http://unix.stackexchange.com/q/164328/74329 – Cyrus

ответ

1

Правильный способ справиться с этим, чтобы окружить переменные в двойные кавычки.

var=/foo/bar baz 
CMD $var # CMD /foo/bar baz 

Приведенный выше код будет выполняться CMD на/Foo/бар и БАЗ

CMD "$var" 

Это будет выполнять CMD на "/ Foo/бар Баз". Лучше всего всегда окружать переменные двойными кавычками в большинстве мест.

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, потому что он содержит маски/маски, которые вы хотите развернуть, и потенциальные пространства, которые вы не хотите использовать для слова. Самый простой способ, это просто не поставить его в переменную и вместо того, чтобы записать его:

for f in "$dir"/* 
do 
    ... 
Смежные вопросы