4

Это кажется тривиальной проблемой, но решение очень осторожно ускользает от меня.

Я хочу очистить много текстовых файлов; лог-файлы. Причина? Для экономии места на диске.

С одним текстовым файлом это так же тривиально, как echo '' > path/to/file.txt

Тем не менее, файлов много. Я прибег к использованию find и xargs . Но я не знаю, как обойти "перенаправление ввода" .

Я пытался find . -name <regex> | xargs -I target echo '' > target and echo '' > { find . -name <regex> | xargs -I target target } ; никто не работал

Я не очень хорошо разбираюсь в написании сценариев, поэтому любая помощь приветствуется.

Благодарю.

3 ответа3

9

То, что вы сделали в обоих ваших примерах, - это поместите > где текущая оболочка может видеть это, так что перенаправление выполняется только один раз, до того, как команды find и xargs будут выполнены. Это твоя первая проблема.

Ваша вторая проблема заключается в том, что если вы заключите в кавычки > чтобы он был передан xargs , он все равно не будет работать, потому что xargs не передает вашу команду через оболочку, если вы не попросите об этом.

Ваша третья проблема заключается в том, что если вы скажете xargs использовать оболочку для запуска команды, оболочка сделает неправильное действие, если в именах файлов есть забавные символы. (Также xargs делает неправильные вещи с забавными персонажами, но это можно исправить с помощью -0 .)

Другие проблемы, которые могут вас не волновать, включают в себя:

  • echo '' создает не пустой файл, а файл, содержащий новую строку.
  • опция -name принимает глобальное выражение, а не регулярное выражение.
  • Вы можете добавить -type f всякий случай, если какие-либо каталоги соответствуют глобусу.

Вот частично исправленная версия команды:

find . -name '*thisisaglob*' -type f -print0 |
xargs -0 -I target sh -c ': > target'

Это решает большинство проблем, которые я упомянул. Тем не менее, остается проблема неправильной интерпретации оболочки имени файла, содержащего метасимволы оболочки. Чтобы это исправить, вам нужно будет указать имя файла для оболочки как параметр, а не как часть команды -c . Это будет выглядеть так:

find . -name '*thisisaglob*' -type f -print0 |
xargs -0 -I target sh -c ': > "$1"' fnord target

"Фнорд" является заполнителем. Это становится $0 котором мы не нуждаемся.

Теперь, достигнув цели безопасного использования xargs и redirection, я покажу вам, как достичь своей цели, не используя ни один из них.

find . -name '*thisisaglob*' -type f -exec truncate -s 0 '{}' +

Для этого требуется команда truncate , которая является частью GNU coreutils, а не стандартной утилитой unix, поэтому она менее переносима, но намного проще для чтения, не так ли?

2

Хотя ответ Алана Карри является полным, точным и очень знающим, у меня есть один вопрос. Почему вы хотите, чтобы файлы продолжали существовать, даже пустые?

Моя естественная рекомендация:

find . -name <glob> -print0 | xargs -0 rm

Если вам нужно, чтобы файлы существовали по какой-то причине, вы можете выполнить ряд команд:

find . -name <glob> -print0 | tee /tmp/filelist | xargs -0 rm
cat /tmp/filelist | xargs -0 touch

Если вы просто хотели сжать файлы (например, если они были в основном избыточной / повторяющейся информацией, но вы хотели сэкономить место и сохранить файлы), вы можете попробовать:

find . -name <glob> -print0 | xargs -0 tar -xzf /tmp/logfiles.tgz
0

Если у вас установлен GNU Parallel http://www.gnu.org/software/parallel/, вы можете сделать это:

find . -name '*thisisaglob*' -type f | parallel '>'

Вы можете установить GNU Parallel просто:

wget http://git.savannah.gnu.org/cgit/parallel.git/plain/src/parallel
chmod 755 parallel
cp parallel sem

Посмотрите вступительные видео для GNU Parallel, чтобы узнать больше:https://www.youtube.com/playlist?list=PL284C9FF2488BC6D1

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .