Подсчитать количество файлов, не являющихся символьными ссылками, в выводе «locate»

man shutdown (8) говорит:

Первым аргументом может быть строка времени (обычно это «сейчас»).

Строка времени может быть в формате «чч: мм» для часов / минут, указывающих время для выполнения выключения, заданного в 24-часовом формате. В качестве альтернативы это может быть синтаксис «+ m», относящийся к указанному количеству минут m с этого момента. «сейчас» - это псевдоним для «+0», то есть для немедленного отключения. Если аргумент времени не указан, подразумевается «+1».

Попробуйте:

# shutdown +5
# systemctl status systemd-shutdownd.service

Вы должны увидеть что-то вроде этого:

● systemd-shutdownd.service - Delayed Shutdown Service
Loaded: loaded (/lib/systemd/system/systemd-shutdownd.service; static; vendor preset: enabled)
Active: active (running) since Tue 2015-09-15 09:13:11 UTC; 12s ago
Docs: man:systemd-shutdownd.service(8)
Main PID: 965 (systemd-shutdow)
Status: "Shutting down at Tue 2015-09-15 09:18:11 UTC (poweroff)..."
CGroup: /system.slice/systemd-shutdownd.service
       └─965 /lib/systemd/systemd-shutdownd

Статус - Выключение во вторник, 15 сентября 2015 г., 09:18:11 UTC (отключение питания) ...

0
13.04.2018, 03:01
4 ответа

С GNU Parallel это выглядит так:

locate -r "$PWD.*\.c$" | parallel 'test -f {} && echo "regular file"' | wc -l

Как видите, это очень похоже на вашу первоначальную попытку.

Если у вас менее 100 совпадений, вы можете использовать наборы GNU Parallel $? к количеству неудачных заданий до 100 (ЭТО НЕ МАСШТАБИРУЕТСЯ):

ls  *txt | parallel \! test -f {}
echo $?

Если нужно еще быстрее:

locate -r "$PWD.*\.c$" |
  perl -ne 'chomp; -l $_ or $s+= -f $_; END{print "$s\n"}'

Или комбинация:

locate -r "$PWD.*\.c$" |
  parallel --block 10k --pipe -q perl -ne 'chomp; -l $_ or $s+= -f $_; END{print "$s\n"}' |
  awk '{s+=$1} END {print s}'
1
28.01.2020, 02:14

Сzsh:

set -o extendedglob # best in ~/.zshrc
c_regular_files=(
  ${(0)^"$(locate -0 "${${PWD%/}//(#m)[]\\*?]/\\$MATCH}/*.c")"}(N.)
)
echo there are at least $#c_regular_files regular files whose name ends in.c
  • Нам нужно экранировать [, ?, \и *в $PWD, чтобы locateне интерпретировать их как операторы подстановки (с -rбыло бы еще хуже для регулярных выражений, которые имеют больше операторов, включая ., общие в именах файлов)
  • $PWD== /требует особой обработки; с $PWDвместо ${PWD%/}мы будем запускать locate -0 "//*.c", который ничего не вернет.
  • -0для файлов, которые должны быть NUL -с разделителями (новая строка не будет работать, так как это разрешено в путях к файлам ).
  • .для обычного файла. В отличие от [ -f, это исключает символические ссылки на обычный файл. Если вы хотите, чтобы каждый не -символическая ссылка .cфайл (разрешал любой другой тип файла, такой как каталог, fifo, сокет... ),замените .на ^@.

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

2
28.01.2020, 02:14

Эта команда приблизилась:

locate -r "$PWD.*\.c$" | xargs -0 -I{} test -f {} && echo "regular file" | wc -l

Проблемы:

  • Вы используете ввод с нулевыми разделителями с xargs, но locateне предоставляет вывод с нулевыми разделителями.
  • && echoвыполняется для трубы locate | xargsв целом, а не для отдельных участков test
  • .

Попробуйте:

locate -0r "$PWD.*\.c$" | xargs -0 -I{} sh -c 'test -f "$1" && echo "regular file"' _  {} | wc -l
  • включение вывода с нулевым разделителем для locateс-0
  • объединение testиecho(это можно улучшить с помощью цикла по аргументам в sh -c, чтобы несколько файлов обрабатывались при вызовеsh)

В $PWDпо-прежнему существует проблема с операторами регулярных выражений.

2
28.01.2020, 02:14

Вместо синтаксического анализа выходных данных locate(, которые являются ненадежными и могут пропустить данные, которые изменились с момента последнего обновления базы данных или которые недоступны для всех пользователей ), используйте find. ].

Далее будут найдены все .cфайлы в текущем каталоге, которые являются обычными файлами, (не символическими ссылками):

find. -type f -name '*.c'

Учитывая структуру каталогов

.
|-- file-a.c
|-- file-b.c
|-- file-c.c
|-- file-d.c
|-- link-b.c -> file-b.c
`-- link-d.c -> file-d.c

Это вернет

./file-a.c
./file-b.c
./file-c.c
./file-d.c

Сосчитать их:

find. -type f -name '*.c' | wc -l

или, если у вас есть имена файлов с символами новой строки в именах,

find.//. -name '*.c' -type f | grep -c //

То же самое для символических ссылок потребует замены -type fна -type l.

2
28.01.2020, 02:14

Теги

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