Загрузка данных
Давайте разберем эту конвейерную команду по шагам. Она обрабатывает файл suid_sgid.txt, содержащий полные пути к файлам (по одному на строку).
Исходные данные
Файл suid_sgid.txt содержит строки вида:
text
/usr/bin/passwd
/usr/bin/sudo
/usr/lib/dbus-1.0/dbus-daemon-launch-helper
/bin/su
/usr/bin/passwd
/bin/mount
Разбор команды по частям
1. cat suid_sgid.txt
Действие: Выводит содержимое файла в stdout
Результат: Поток строк с полными путями файлов
2. | awk -F '/' '{$NF=""; print $0}'
-F '/' : Устанавливает разделитель полей (Field Separator) — символ /
$NF : NF = Number of Fields, $NF — последнее поле (имя файла)
{$NF = ""; print $0} : Обнуляет последнее поле (стирает имя файла), затем печатает всю строку $0
Результат: Из каждого пути удаляется имя файла, остаются каталоги с завершающим слэшем
Пример преобразования:
text
Вход: /usr/bin/passwd
Поля: "" | "usr" | "bin" | "passwd"
$1 $2 $3 $4($NF)
После: /usr/bin/
(потому что $4 стал пустым, а разделители на месте)
Проблема: AWK выводит поля, разделенные FS (/), но пустое последнее поле создает два смежных разделителя:
text
/usr/bin/ ← Здесь два слэша? Нет, AWK выводит /usr/bin/
Фактически: FS между $1($2) и $2($3): /usr/bin
Пустой $NF не добавляет слэш автоматически
3. | tr ' ' '/'
Действие: Заменяет все пробелы на слэши
Важно: AWK выводит поля, разделенные пробелом (по умолчанию OFS=" ")
AWK что вывел на самом деле:
text
/usr/bin/ ← но здесь нет пробелов... Стоп!
Проблема в анализе: В AWK print $0 печатает строку с разделителями полей (ORS — Output Field Separator, по умолчанию пробел), но здесь $0 — пересобранная строка с удаленным полем. На самом деле AWK выводит пробелы как разделители между частями пути.
Пример с отладкой:
text
echo "/usr/bin/passwd" | awk -F '/' '{$NF=""; print $0}'
Вывод: /usr/bin/ (с пробелом? нет — но это зависит от реализации)
Честно говоря, в классическом AWK print $0 выводит поля, соединенные OFS (пробел). Без имени файла будет:
text
/ usr bin → между ними пробелы!
4. | sort
Действие: Сортирует все строки в алфавитном порядке
Результат: Одинаковые каталоги группируются вместе
5. | uniq -c
Действие: Подсчитывает количество одинаковых строк
-c: Count — показывает число повторений перед каждой уникальной строкой
ИТОГОВЫЙ СМЫСЛ КОМАНДЫ
Команда считает, сколько раз каждый каталог встречается в списке файлов (без учета самих файлов).
Более чистый эквивалент:
bash
cat suid_sgid.txt | awk -F '/' '{print $(NF-1)}' | sort | uniq -c
# или еще проще:
awk -F '/' '{print $(NF-1)}' suid_sgid.txt | sort | uniq -c
Пример работы:
Вход (suid_sgid.txt):
text
/usr/bin/passwd
/usr/bin/sudo
/usr/lib/security/pam_rootok.so
/bin/su
/usr/bin/crontab
/bin/mount
Вывод команды:
text
2 bin
1 lib
2 usr
Потому что:
bin встречается 2 раза (у /bin/su и /bin/mount — но тут ошибка, /bin/mount дает каталог bin)
usr встречается 3 раза? Нет, passwd, sudo, crontab — все в /usr/bin
Лучше переписать правильно:
bash
awk -F '/' '{
# Удалить последнее поле (имя файла)
path = ""
for(i=1; i<NF; i++) {
path = path "/" $i
}
print path
}' suid_sgid.txt | sort | uniq -c
Типичный вывод:
text
3 /usr/bin
2 /bin
1 /usr/lib/security
1 /usr/lib/dbus-1.0
Проблемы исходной команды:
tr ' ' '/' странная — если в AWK уже есть слэши, замена пробелов делает кашу
На выходе будут каталоги с лишними пробелами или двойными слэшами
Лучше использовать чистое решение без tr
Вывод: Команда пытается сгруппировать файлы по каталогам и подсчитать количество файлов SUID/SGID в каждом каталоге, но из-за tr делает это некорректно.