Вопрос об отладочной ловушке

Если вы используете инструменты GNU (, которые являются стандартными для Linux ), вы можете сделать что-то вроде этого:

stat --printf '%s\t%n\0'./* | 
  sort -z -rn | 
  head -z -n 5 | 
  cut  -z -f 2- |
  xargs -0 -r echo rm -f --

(удалите "эхо" после того, как вы протестировали его ).

Команда statвыводит размер файла и имя каждого файла в текущем каталоге, разделенные табуляцией, и каждая запись завершается байтом NUL (\0 ).

Команда sortсортирует каждую запись с завершением NUL -в обратном числовом порядке. Команда headвыводит только первые пять таких записей, затем cutудаляет поле размера файла из каждой записи.

Наконец, xargsпринимает этот (все еще NUL -завершенный )ввод и использует его в качестве аргументов для echo rm -f.

Поскольку в качестве терминатора записи (имени файла )используется NUL, он работает с именами файлов, содержащими любой допустимый символ.

Если вам нужен минимальный размер файла, вы можете вставить awkили что-то между statи sort. например.

stat --printf '%s\t%n\0'./* | 
  awk 'BEGIN {ORS = RS = "\0" } ; $1 > 25000000' |
  sort -z -rn |...

ПРИМЕЧАНИЕ. :GNU awkне имеет опции -zдля записей с завершением NUL -, но позволяет вам установить разделитель записей на любое значение, которое вы хотите. Мы должны установить для разделителя выходных записей (ORS )и разделителя входных записей (RS )значение NUL.


Вот еще одна версия, которая использует findдля явного ограничения себя обычными файлами (, т.е. исключая каталоги, именованные каналы, сокеты и т. д. )только в указанном каталоге (-maxdepth 1, без подкаталогов )] размером более 25M (нет необходимости вawk).

Эта версия не нуждается в stat, потому что GNU findтакже имеет функцию printf. Кстати, обратите внимание на разницу в строке формата-statиспользует %nдля имени файла, а findиспользует %p.

find. -maxdepth 1 -type f -size +25M -printf '%s\t%p\0' | 
  sort -z -rn | 
  head -z -n 5 | 
  cut  -z -f 2- |
  xargs -0 -r echo rm -f --

Чтобы запустить его для другого каталога, замените .в команде find. например.find /home/web/....


версия сценария оболочки:

#!/bin/sh

for d in "$@" ; do
  find "$d" -maxdepth 1 -type f -size +25M -printf '%s\t%p\0' | 
    sort -z -rn | 
    head -z -n 5 | 
    cut  -z -f 2- |
    xargs -0 -r echo rm -f --
done

сохраните его как, например, delete-five-largest.shгде-нибудь в вашем PATH и запустите какdelete-five-largest.sh /home/web /another/directory /and/yet/another

Это запускаетfind...один раз для каждого каталога , указанного в командной строке. Это НЕ то же самое, что и однократный запуск findс несколькими аргументами пути (, который будет выглядеть как find "$@"..., без какого-либо forцикла в сценарии ). Он удаляет 5 самых больших файлов в каждом каталоге, а его запуск без цикла for удалит только пять самых больших файлов, найденных при поиске во всех каталогах. то есть пять на каталог против пяти всего.

0
10.06.2019, 17:28
1 ответ

Ловушка вызывается после каждой установленной командной строки. Как показано с помощью вывода TRACE ниже:

+ badvar=0
+ set -o functrace
+ trap dbgtrap DEBUG
++ dbgtrap
++ echo 'badvar is 0'
badvar is 0
+ some_func
++ dbgtrap
++ echo 'badvar is 0'
badvar is 0
++ dbgtrap
++ echo 'badvar is 0'
badvar is 0
+ badvar=1
++ dbgtrap
++ echo 'badvar is 1'
badvar is 1
+ badvar=2
++ dbgtrap
++ echo 'badvar is 2'
badvar is 2
+ badvar=3
++ dbgtrap
++ echo 'badvar is 3'
badvar is 3
+ trap - DEBUG

Оболочка IIRC вызывает ловушку в конце обработки, поэтому 3 строки вывода перед вызовом функции выводят значения badvar.

2
28.01.2020, 02:30

Теги

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