comm(1)
инструмент, который сравнивает два списка и может дать Вам пересечение или различие между двумя списками. Списки должны быть отсортированы, но этого легко достигнуть.
Получить Ваши массивы в отсортированный список, подходящий для comm
:
$ printf '%s\n' "${A[@]}" | LC_ALL=C sort
Это повернет массив в отсортированный список. Сделайте то же для B.
Использовать comm
возвратить пересечение:
$ comm -1 -2 file1 file2
-1 -2
говорит для удаления записей, уникальных для file1 (A) и уникальный для file2 (B) - пересечение двух.
Чтобы иметь его возвращают то, что находится в file2 (B), но не file1 (A):
$ comm -1 -3 file1 file2
-1 -3
говорит для удаления записей, уникальных для file1 и характерных для обоих - отъезд только уникальных для file2.
Подавать два конвейера в comm
, используйте функцию "Process Substitution" bash
:
$ comm -1 -2 <(pipeline1) <(pipeline2)
Получать это в массиве:
$ C=($(command))
Соединение всего этого:
# 1. Intersection
$ C=($(comm -12 <(printf '%s\n' "${A[@]}" | LC_ALL=C sort) <(printf '%s\n' "${B[@]}" | LC_ALL=C sort)))
# 2. B - A
$ D=($(comm -13 <(printf '%s\n' "${A[@]}" | LC_ALL=C sort) <(printf '%s\n' "${B[@]}" | LC_ALL=C sort)))
Можно написать сценарий, в котором будет сохранено количество пользователей, зарегистрированных в данный момент в файле, и общее число пользователей в другом файле, и выполнить над ними comm
.
Например:
#!/bin/bash
w | awk 'NR > 2 {print $1}' | sort > logged.txt #sorted list of logged users
awk -F':' '{ print $1}' /etc/passwd | sort > allusers.txt #sorted list of all users
comm -23 allusers.txt logged.txt #find lines unique to allusers.txt
-121--125664- Вы ошиблись при выводе хотя бы одной команды. Разрешения символьной ссылки всегда имеют значение rwxrwxrwx
или вообще не имеют разрешений:
$ touch file
$ ls -l
total 0
-rw-rw-r-- 1 muru muru 0 Dec 5 20:53 file
$ ln -s file link
$ ls -l
total 0
-rw-rw-r-- 1 muru muru 0 Dec 5 20:53 file
lrwxrwxrwx 1 muru muru 4 Dec 5 20:53 link -> file
$ chmod a+x file
$ ls -l
total 0
-rwxrwxr-x 1 muru muru 0 Dec 5 20:53 file
lrwxrwxrwx 1 muru muru 4 Dec 5 20:53 link -> file
Дополнительные сведения см. в разделе Часто задаваемые вопросы по FreeBSD .
И так как вы находитесь в Linux, man chmod
говорит:
chmod never changes the permissions of symbolic links; the chmod system
call cannot change their permissions. This is not a problem since the
permissions of symbolic links are never used. However, for each
symbolic link listed on the command line, chmod changes the permissions
of the pointed-to file. In contrast, chmod ignores symbolic links
encountered during recursive directory traversals.
-121--125670- Вы можете получить список всех ваших локальных пользователей с помощью этой команды:
$ getent passwd | awk -F: '{print $1}'
ПРИМЕЧАНИЕ: getent
вернет локальных пользователей при условии, что у вас нет sssd
(или аналогичной службы, которая также привлекает пользователей LDAP), и ваш /etc/nsswitch.conf
ограничен файлами, т.е. он не включает такие вещи, как NIS или NIS +. Только для локального пользователя можно обратиться к awk -F: '{print $1} '/etc/passwd
.
Список пользователей, которые в настоящее время вошли в систему:
$ who
Список пользователей, которые в настоящее время не вошли в систему:
$ grep -Fxvf <(who | awk '{print $1}' | sort -u) \
<(getent passwd | awk -F: '{print $1}')
Этот последний список берет список пользователей, которые вошли в систему, и показывает список всех пользователей за вычетом зарегистрированных пользователей, используя grep-vf
.
Чтобы получить счетчики, просто переведите wc -l
в конец команд.
$ grep -Fxvf <(who | awk '{print $1}' | sort -u) \
<(getent passwd | awk -F: '{print $1}') | wc -l
53
вошел в систему
$ who | awk '{print $1}' | sort -u | wc -l
1
-F, --fixed-strings
Interpret PATTERN as a list of fixed strings, separated by newlines,
any of which is to be matched.
-x, --line-regexp
Select only those matches that exactly match the whole line.
-v, --invert-match
Invert the sense of matching, to select non-matching lines.
-f FILE, --file=FILE
Obtain patterns from FILE, one per line. The empty file contains
zero patterns, and therefore matches nothing.
Можно также отказаться от использования grep
и использовать join
вместо этого, так как этот тип проблемы больше в рулевой рубке join
. Нам нужно будет использовать join -v 2
, что означает, что мы хотим исключить совпадения и показать только уники из нашего второго аргумента, getent...
.
-a FILENUM
also print unpairable lines from file FILENUM, where FILENUM is
1 or 2, corresponding to FILE1 or FILE2
-v FILENUM
like -a FILENUM, but suppress joined output lines
$ join -v 2 <(who | awk '{print $1}' | sort -u) \
<(getent passwd | awk -F: '{print $1}' | sort) | wc -l
53
ПРИМЕЧАНИЕ: Единственное замечание при использовании join
состоит в том, что оба списка необходимо отсортировать, поэтому необходимо добавить | sort
к getent...
.
Возможно, вы захотите написать скрипт, в котором будет сохранено количество пользователей, зарегистрированных в настоящее время в одном файле, и общее количество пользователей в другом файле, и сделать над ними комментарий
.
Например:
#!/bin/bash
w | awk 'NR > 2 {print $1}' | sort > logged.txt #sorted list of logged users
awk -F':' '{ print $1}' /etc/passwd | sort > allusers.txt #sorted list of all users
comm -23 allusers.txt logged.txt #find lines unique to allusers.txt
Этот одноклассник будет работать:
grep -Ev $(users | sed 's/ /|/g') /etc/passwd | awk -F: {'print $1'}
Как это работает :
Выход Пользователи |. SED 'S / / | / G'
даст вам |
разделенный список зарегистрированных пользователей.
Опция -E
с GREP позволит нам использовать более одной строки (в или состоянии), чтобы соответствовать. Параметр -V
распечатает то, что не соответствует указанным строкам / шаблону. Сочетание --e и -V
вместе будет перечислять все строки, которые не содержат трубопроводных строк с выхода пользователей | Sed 'S / / | / G'
. В конце применения awk
отфильтровать только имена пользователей.