Невозможно надежно проверить, поддерживает ли терминал курсив. Вы можете, проверив вывод tput sitm
или tput ritm
, проверить, требует ли значение $ TERM
и соответствующее описание терминала ], чтобы поддержать это, но утверждение и фактическое поведение могут легко не синхронизироваться в любом направлении.
Я действительно сомневаюсь, что консоль Linux поддерживает или будет поддерживать курсив в обозримом будущем.
Вы бы хотели использовать только:
find. -name '*.txt' -exec cmd {} \;
форма для тех cmd
s, которые могут принимать только один аргумент. Это не относится к grep
. Сgrep
:
find. -name '*.txt' -exec grep foo /dev/null {} +
(или используйте -H
с GNUgrep
). Подробнее об этом в Recursive grep vs find / -type f -exec grep {} \; Что эффективнее/быстрее?
Теперь для замены, то же самое, perl -pi
может принимать более одного аргумента:
find. -name '*.txt' -type f -exec perl -pi -e s/foo/bar/g {} +
Теперь это будет перезаписывать файлы независимо от того, содержат они foo
или нет. Вместо этого вы можете захотеть (предполагать GNU grep
и xargs
или совместимые):
find. -name '*.txt' -type f -exec grep -l --null foo {} + |
xargs -r0 perl -pi -e s/foo/bar/g
или:
grep -lr --null --include='*.txt' foo. |
xargs -r0 perl -pi -e s/foo/bar/g
Таким образом, перезаписываются только те файлы, которые содержат foo
.
Кстати,--include=*.txt
(--include
является еще одним расширением GNU. )представляет собой шелл-шаблон, поэтому его следует указать в кавычках. Например, если в текущем каталоге есть файл с именем --include=foo.txt
, оболочка расширит --include=*.txt
до него перед вызовом grep
. А если нет, то во многих оболочках вы получите ошибку о том, что glob не соответствует ни одному файлу.
Так и хочетсяgrep --include='*.txt'
Когда ваше выражение find
настолько простое, вы можете вместо этого использовать свою оболочку для выполнения подстановки. Основным ограничением, с которым вы можете столкнуться, будет работа с большим количеством файлов, чем может поместиться в командной строке -.
Пример в bash:
$ shopt -s globstar
$ date > a.txt
$ date > b.txt
$ date > c.txt
$ cat *.txt
Thu Mar 29 14:57:57 EDT 2018
Thu Mar 29 14:58:00 EDT 2018
Thu Mar 29 14:58:02 EDT 2018
$ mkdir -p deep/sub/dir
$ mv *.txt deep/sub/dir
$ perl -pi -e 's/EDT/EST/' **/*.txt
$ cat deep/sub/dir/*.txt
Thu Mar 29 14:57:57 EST 2018
Thu Mar 29 14:58:00 EST 2018
Thu Mar 29 14:58:02 EST 2018
Вы можете использовать find... -exec
с разделителем "+" вместо ";" для запуска файлов большими пакетами вместо одного -в -время -(при условии, что команда exec
ed поддерживает несколько файлов за один вызов):
find. -name '*.txt' -exec grep foo {} +
find. -name '*.txt' -exec perl -i -pe 's/foo/bar/' {} +