Intereting Posts
Что такое пароль по умолчанию для ubuntu для пользователей, созданных с помощью useradd? Имеет ли процесс, который не является процессом оболочки, переменными оболочки? Копия SCP через SSH не работает – в разрешении отказано, и stdin не является tty С легкостью переходите от sylpheed до Thunderbird Как запустить команду (ifup eth0) 10 секунд ПОСЛЕ загрузки настольного компьютера? Согласованность в каталогах установки по умолчанию Как я могу применить фильтры procmail к почтовому ящику maildir? privoxy не может выполнять никаких дополнительных подключений Файлы Cat, кроме одного Программа Bash не выполняется, если перенаправление не сработает Можно загрузить все пакеты из «groupinstall», а затем запустить (yum –nogpgcheck localinstall *. Rpm)? Предоставить пользователю разрешение на доступ к файлам в каталоге Получить имена пакетов для динамических наборов в Gentoo Linux sed на cygwin может заменить только одного персонажа? E470 TrackPoint не работает в CentOS 7

запускать команды внутри awk перед печатью

Я хочу перечислять каталоги при расчете их размера и печатать все в простой команде, используя ls и awk , отлично справляется с управлением списком и тем, что я хочу отображать:

ls -AlhF /usr | awk '{print $6, $7, $8, "\011", $9 }'

Но я хотел бы пойти немного дальше, чтобы получить размер папок или файлов, используйте $ 9 с командой du -s с чем-то вроде этого:

ls -AlhF /usr | awk '{print $6, $7, $8, "\011", $9, du -s /usr/$9 }'

Я пробовал много способов написать его, с backticks, doublequote, но я всегда получаю ошибки или нежелательные результаты.

Чтобы ответить на вопрос и проигнорировать вопросы о разборе вывода ls на данный момент, чтобы получить вывод (stdout) команды в awk , выполните следующие действия:

 cmd="that command" output="" while ((cmd | getline line) > 0) output = output line RS status = close(cmd) 

Как состояние выхода закодировано в переменной состояния, варьируется от одной реализации awk к другому. Все, на что вы можете положиться, это то, что он будет равен 0, если и только если cmd успешно cmd .

getline запускает оболочку (обычно это оболочка POSIX, но в некоторых системах, которая может быть оболочкой Bourne) для синтаксического анализа этой командной строки. Поэтому важно правильно указывать данные там. Лучше всего использовать одинарные кавычки, которые являются самыми безопасными.

Здесь, так как выход будет одной строкой в ​​любом случае (ваш подход не может обрабатывать имена файлов с любыми символами пробела, не говоря уже о символах новой строки), вам нужно всего лишь сделать один getline :

  awk -vq="'" ' function shquote(s) { gsub(q, q "\\" qq, s) return qsq } { cmd = "du -sk " shquote("/usr/" $9) cmd | getline du_output status = close(cmd) }' 

Если вы вызываете getline без имени переменной, то она устанавливает $0 что упрощает извлечение дискового пространства:

 DIR=/usr export DIR LC_ALL=C ls -l -- "$DIR" | awk -vq="'" ' function shquote(s) { gsub(q, q "\\" qq, s) return qsq } { date = $6 " " $7 " " $8 name = $9 cmd = "du -sk " shquote(ENVIRON["DIR"] (ENVIRON["DIR"] ~ /^\/*$/ ? "" : "/") name) cmd | getline disk_usage = $1 print date "\t" name "\t" disk_usage }' 

Вот реализация perl которая не зависит от разбора вывода ls -l (который по своей сути ненадежен) и может быть легко изменен для использования любого формата вывода даты или формата.

Сохраните его в файл, сделайте его исполняемым и запустите его как /path/to/script /usr . Для сценария требуется один или несколько аргументов имени каталога.

 #!/usr/bin/perl use strict; use Date::Format; if ($#ARGV < 0) { die "Missing directory argument" }; foreach my $dir (@ARGV) { $dir =~ s:/+$::; # strip trailing / opendir(my $dh, $dir) || die "Can't opendir $dir: $!"; while (readdir $dh) { next if (m/^\.{1,2}$/); # skip . and .. entries my $mtime=(stat("$dir/$_"))[9]; # extract mtime field from stat my $mtime_f = time2str('%Y-%m-%d %X', $mtime); open(my $fh, "-|", 'du', '-s', '--', "$dir/$_"); my $du = <$fh>; ($du) = split(' ',$du); # only want the first blank-separated field close($fh). printf "%s\t%s\t%s\n", $mtime_f, "$dir/$_" , $du; } closedir $dh; }; 

Есть более простые и более короткие способы сделать это (в perl или awk или на других языках), но это дает полезную базу для сообщения другой информации о каталогах и их содержимом. см. perldoc -f stat для получения полной информации об информации, доступной из функции stat() .

BTW, это может быть реализовано в awk , но вам придется реализовать свою собственную функцию stat() и функцию форматирования даты. Легче использовать perl .

GNU awk aka gawk поддерживает загружаемые модули, а модуль filefuncs предоставляет stat() который заполняет массив statdata[] . Используйте, добавив @load "filefuncs" в верхней части вашего awk скрипта.

 ls -AlhF /usr | awk '{print "echo "$6" "$7" "$8" \011 "$9" $(du -s /usr/"$9")" }' | sh 

Постройте эхо и команду du с awk, а затем выполните ее через трубопровод sh.