Быстрая замена строки в рекурсивных каталогах

Невозможно надежно проверить, поддерживает ли терминал курсив. Вы можете, проверив вывод tput sitm или tput ritm , проверить, требует ли значение $ TERM и соответствующее описание терминала ], чтобы поддержать это, но утверждение и фактическое поведение могут легко не синхронизироваться в любом направлении.

Я действительно сомневаюсь, что консоль Linux поддерживает или будет поддерживать курсив в обозримом будущем.

0
29.03.2018, 23:22
3 ответа

Вы бы хотели использовать только:

 find. -name '*.txt'  -exec cmd {} \;

форма для тех cmds, которые могут принимать только один аргумент. Это не относится к 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'

5
28.01.2020, 02:14

Когда ваше выражение 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
2
28.01.2020, 02:14

Вы можете использовать find... -execс разделителем "+" вместо ";" для запуска файлов большими пакетами вместо одного -в -время -(при условии, что команда execed поддерживает несколько файлов за один вызов):

find. -name '*.txt' -exec grep foo {} +
find. -name '*.txt' -exec perl -i -pe 's/foo/bar/' {} +
0
28.01.2020, 02:14

Теги

Похожие вопросы