Если вы не укажете имя файла в кавычках, оболочка не сможет узнать, что foo bar.txt
- это один параметр, а не два ( foo
и bar.txt
).Поэтому вам нужно вызвать свой сценарий следующим образом:
./chExt.sh txt ocelot.cpp ../otherFolder/file.H cat.dog.TXT "king cobra.dat"
Следующая проблема заключается в том, что при раскрытии переменных результирующее значение разбивается на пробелы (или что-то еще, что переменная $ IFS
является установлен в). Итак, когда вы пишете для i в $ *
, $ *
расширяется и разбивается на пробелы. Следовательно, $ i
становится королем
для одной итерации и cobra.txt
для следующей. Чтобы избежать этого, укажите переменную, которую вы хотите расширить, в кавычки, чтобы она не разделялась.
Это подводит нас к следующему вопросу - разнице между $ *
и $ @
. Если вы используете «$ *»
, все параметры будут обрабатываться как одна длинная строка:
$ cat foo.sh
#!/bin/sh
for i in "$*"; do
echo "$i"
done
$ foo.sh foo "bar baz"
foo bar baz
Сравните приведенное выше с:
#!/bin/sh
for i in "$@"; do
echo "$i"
done
$ foo.sh foo "bar baz"
foo
bar baz
Как видите, используя «$ @»
имеет желаемый эффект, каждый входной параметр обрабатывается отдельно, в том числе и параметр с пробелами.
В заключение, ваш сценарий также будет подавляться именами файлов, начинающимися с -
и буквой, соответствующей параметру для echo
(попробуйте с файлом с именем - новый
, например). Лучший способ избавиться от расширения - использовать встроенные в оболочку функции обработки строк . $ {var%. *}
удаляет самую короткую строку, совпадающую с .
и 0 или более символов с конца переменной. Другими словами, расширение.Затем вам также необходимо добавить -
к mv
, чтобы указать конец параметра и начало параметров, чтобы он также мог обрабатывать имена файлов, начинающиеся с -
(см. Правило 10 здесь ).
Итак, улучшенная и рабочая версия вашего сценария будет выглядеть так:
#!/bin/sh
newExt="$1"
shift
for fileName in "$@"
do
if test -f "$fileName";
then
# name=$(echo "$fileName" | rev | cut -f 2- -d '.' | rev)
name=${fileName%.*}
newName="$name.$newExt"
if test "$newName" != "$fileName";
then
mv -- "$fileName" "$newName"
fi
else
printf '%s: No such file\n' " $fileName"
fi
done
Дополнительная литература:
]
У вас есть 2 пути.
--exclude=dir
и нет разницы локальная она или удаленная, так как все равно синхронизировать не хочется. --rsync-path='rsync --exclude=dir'
, и удаленная rsync будет выполнена с этой опцией исключения. Это должно работать:
rsync -av --delete --exclude=/xyz/ sourcepath/ root@IPADDRESS:remotepath/
Это исключает "xyz", когда он встречается в корне "sourcepath", и является каталогом (, завершающий "/" гарантирует, что ).
Завершающие косые черты в исходном и целевом каталогах важны. Без этого второй запуск rsync создал бы новую папку «remotepath/sourcepath», что, вероятно, не то, что вам нужно.
Кроме того, согласно вашему описанию (у вас были неверные параметры источника и назначения, но путаница может быть моей ).