Сущность этого совпадает с ответом unxnut, но я думаю с помощью sed для чего-то как простой, поскольку разделение расширения является путем излишество:
for f in ./*.py; do mv "$f" "${f%.py}-backup.py"; done
${f%.py}
переменный $f, с .py
разделенный от конца. Можно также удалить вещи из начала ${f#whatever}
. Для рекурсивности (т.е. работающий в текущем каталоге и всех подкаталогах), принимая у Вас есть удар 4 +, можно использовать globstar:
shopt -s globstar
for f in ./**/*.py; do mv "$f" "${f%.py}-backup.py"; done
С другой стороны, можно использовать, переименовывают - существует на самом деле две различных программы, которые используют это имя, и какой, который Вы имеете, будет зависеть от Вашего аромата *, отклоняют. perl-переименуйте (используемый Debian и его производными, такими как Ubuntu и многие другие):
rename 's/\.py$/-rename.py/' ./*.py
Другой переименовывать использовал бы этот синтаксис:
rename .py -backup.py ./*.py
for
цикл с mv
является более портативным, конечно: первый, нерекурсивный является POSIX и так продолжит работать каждый *, отклоняют где угодно, кроме, возможно, некоторых музейных экспонатов.
Оболочка POSIX имеет единый массив: позиционные параметры ($1
, $2
, ...), коллективно доступные как "$@"
, и установленные со встроенным набором --
. Точнее, на каждый экземпляр функции в текущем стеке вызовов есть один массив, но в любой момент доступен только массив позиционных параметров функции currrent (или скрипта, если он находится вне какой-либо функции). Таким образом, если вы хотите использовать этот массив, но не засорять параметры скрипта, то работайте в функции.
Так как sml уже заметил, ваш конкретный случай использования grep проще решить с помощью опции -F
grep, чтобы заставить его читать по одному шаблону на файловую строку. Но вот как можно решить ту же проблему для команды, которая не имеет ничего похожего на grep -F
.
set -- -a -b
while IFS= read -r line; do
set -- -e "$line"
done < "$dictionary"
mycommand "$@" more stuff
Это вызывает mycommand -a -b line1 line2 ... больше вещей
.
Если вам необходимо манипулировать несколькими списками имен файлов (или другими строками с произвольным содержимым), вы можете сделать это с помощью eval
и очень осторожного цитирования. Получить кавычки сложно. Следующая функция принимает два аргумента: имя переменной и строку; она добавляет к переменной строку в кавычках. Цитируемая форма - это однокавычный литерал, с одинарными кавычками, подходящими для разбора оболочки.
append_to_quoted_list () {
set -- "$1" "$(printf %s. "$2" | sed "s/'/'\\\\''/")"
eval "$1=\"\${$1} '${2%?}'\""
}
Вот пример использования для построения двух списков одновременно. Он вызывает $command1
со строками, переданными в качестве аргументов в опциях -e
, затем $command2
со строками, переданными в качестве аргументов в опциях --foo=...
.
list1= list2=
append_to_quoted_list list1 "$command1"
append_to_quoted_list list1 "$command2"
while IFS= read -r line; do
append_to_quoted_list list1 -e
append_to_quoted_list list1 "$line"
append_to_quoted_list list2 "--foo=$line"
done < "$dictionary"
eval "$list1; $list2"
С помощью grep
Вы не хотите использовать переключатели -f
или -F
, которые предлагает grep
? Из grep
man page:
-F, --fixed-strings
Interpret PATTERN as a list of fixed strings, separated by
newlines, any of which is to be matched. (-F is specified by
POSIX.)
-f FILE, --file=FILE
Obtain patterns from FILE, one per line. The empty file contains
zero patterns, and therefore matches nothing. (-f is specified by
POSIX.)
$ grep -F somefile.txt -R .